diff --git a/.circleci/config.yml b/.circleci/config.yml index 7961a08..ce5855b 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -10,22 +10,12 @@ workflows: - build-linux - test-linux: name: Java 8 - Linux - OpenJDK - docker-image: circleci/openjdk:8 - requires: - - build-linux - - test-linux: - name: Java 9 - Linux - OpenJDK - docker-image: circleci/openjdk:9 - requires: - - build-linux - - test-linux: - name: Java 10 - Linux - OpenJDK - docker-image: circleci/openjdk:10 + docker-image: cimg/openjdk:8.0 requires: - build-linux - test-linux: name: Java 11 - Linux - OpenJDK - docker-image: circleci/openjdk:11 + docker-image: cimg/openjdk:11.0 with-coverage: true requires: - build-linux @@ -37,7 +27,7 @@ workflows: jobs: build-linux: docker: - - image: circleci/openjdk:8u131-jdk # To match the version pre-installed in Ubuntu 16 and used by Jenkins for releasing + - image: cimg/openjdk:8.0 steps: - checkout - run: cp gradle.properties.example gradle.properties diff --git a/.ldrelease/config.yml b/.ldrelease/config.yml index c1ca1e8..93719a2 100644 --- a/.ldrelease/config.yml +++ b/.ldrelease/config.yml @@ -1,3 +1,5 @@ +version: 2 + repo: public: java-sdk-common private: java-sdk-common-private @@ -8,8 +10,11 @@ publications: - url: https://javadoc.io/doc/com.launchdarkly/launchdarkly-java-sdk-common description: documentation (javadoc.io) -template: - name: gradle +jobs: + - docker: + image: gradle:6.8.3-jdk11 + template: + name: gradle documentation: - githubPages: true + gitHubPages: true diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index be0f1ab..c908b04 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,6 +1,6 @@ # Contributing to the LaunchDarkly SDK Java Common Code -LaunchDarkly has published an [SDK contributor's guide](https://docs.launchdarkly.com/docs/sdk-contributors-guide) that provides a detailed explanation of how our SDKs work. See below for additional information on how to contribute to this project. +LaunchDarkly has published an [SDK contributor's guide](https://docs.launchdarkly.com/sdk/concepts/contributors-guide) that provides a detailed explanation of how our SDKs work. See below for additional information on how to contribute to this project. ## Submitting bug reports and feature requests diff --git a/README.md b/README.md index 5c29584..5821bc4 100644 --- a/README.md +++ b/README.md @@ -20,7 +20,7 @@ See [Contributing](https://github.com/launchdarkly/dotnet-sdk-common/blob/master * Gradually roll out a feature to an increasing percentage of users, and track the effect that the feature has on key metrics (for instance, how likely is a user to complete a purchase if they have feature A versus feature B?). * Turn off a feature that you realize is causing performance problems in production, without needing to re-deploy, or even restart the application with a changed configuration file. * Grant access to certain features based on user attributes, like payment plan (eg: users on the ‘gold’ plan get access to more features than users in the ‘silver’ plan). Disable parts of your application to facilitate maintenance, without taking everything offline. -* LaunchDarkly provides feature flag SDKs for a wide variety of languages and technologies. Check out [our documentation](https://docs.launchdarkly.com/docs) for a complete list. +* LaunchDarkly provides feature flag SDKs for a wide variety of languages and technologies. Read [our documentation](https://docs.launchdarkly.com/sdk) for a complete list. * Explore LaunchDarkly * [launchdarkly.com](https://www.launchdarkly.com/ "LaunchDarkly Main Website") for more information * [docs.launchdarkly.com](https://docs.launchdarkly.com/ "LaunchDarkly Documentation") for our documentation and SDK reference guides diff --git a/build-android.gradle b/build-android.gradle index a7901ec..9c48943 100644 --- a/build-android.gradle +++ b/build-android.gradle @@ -24,7 +24,11 @@ repositories { google() } -apply from: 'build-shared.gradle' +allprojects { + group = ProjectValues.groupId + version = "${version}" // from gradle.properties + archivesBaseName = ProjectValues.artifactId +} android { compileSdkVersion 26 @@ -59,16 +63,14 @@ android { } } -dependencies { - // See note in build-shared.gradle on the purpose of "privateImplementation". The - // Android Gradle plugin doesn't seem to have a good way to customize the classpath - // of the compile and test tasks, but since we're not actually publishing any - // Android artifacts from this project (we use this build only for CI testing), we - // can simply copy the dependencies from "privateImplementation" into the standard - // "implementation" for the Android build. - implementation configurations.privateImplementation - - androidTestImplementation "junit:junit:4.12" - androidTestImplementation "org.hamcrest:hamcrest-library:1.3" - androidTestImplementation "com.android.support.test:runner:1.0.2" +dependencies { // see Dependencies.kt in buildSrc + // See note in Dependencies.kt in buildSrc on the purpose of "privateImplementation". + // The Android Gradle plugin doesn't seem to have a good way to customize the classpath + // of the compile and test tasks, but since we're not actually publishing any Android + // artifacts from this project (we use this build only for CI testing), we can simply + // copy the dependencies from "privateImplementation" into the standard "implementation" + // for the Android build. + Libs.privateImplementation.each { implementation(it) } + Libs.javaTestImplementation.each { testImplementation(it) } + Libs.androidTestImplementation.each { androidTestImplementation(it) } } diff --git a/build-shared.gradle b/build-shared.gradle deleted file mode 100644 index 085dd5f..0000000 --- a/build-shared.gradle +++ /dev/null @@ -1,52 +0,0 @@ - -// These properties are in their own file to ensure that they're kept in sync between the -// main Java build (build.gradle) and the Android CI build (build-android-ci.gradle). - -allprojects { - group = 'com.launchdarkly' - version = "${version}" - archivesBaseName = "launchdarkly-java-sdk-common" - sourceCompatibility = 1.7 - targetCompatibility = 1.7 -} - -ext { - sdkBasePackage = "com.launchdarkly.sdk" - sdkBaseName = "launchdarkly-java-sdk-common" -} - -ext.versions = [ - "gson": "2.7", - "jacksonCore": "2.10.5", - "jacksonDatabind": "2.10.5.1" -] - -ext.libraries = [:] - -configurations { - privateImplementation -} - -dependencies { - // The Gson and Jackson dependencies go into a custom configuration here, instead of - // the regular "implementation" configuration. We don't want them to be visible at - // all in the module's published dependencies - not even in "runtime" scope - because: - // - // 1. For Gson: While java-sdk-common does need Gson in order to work, the - // LaunchDarkly SDKs that use java-sdk-common have different strategies for packaging - // Gson. The Android SDK exposes it as a regular dependency; the Java server-side SDK - // embeds and shades Gson and does not expose it as a dependency. So we are leaving - // it up to the SDK to provide Gson in some way. - // - // 2. For Jackson: The SDKs do not use, require, or embed Jackson; we provide the - // LDJackson class as a convenience for applications that do use Jackson, and it is - // only usable if the application already has Jackson in its classpath. So we do not - // want Jackson to show up as a transitive dependency. - privateImplementation "com.google.code.gson:gson:${versions.gson}" - privateImplementation "com.fasterxml.jackson.core:jackson-core:${versions.jacksonCore}" - privateImplementation "com.fasterxml.jackson.core:jackson-databind:${versions.jacksonDatabind}" - - testImplementation configurations.privateImplementation - testImplementation "org.hamcrest:hamcrest-library:1.3" - testImplementation "junit:junit:4.12" -} diff --git a/build.gradle.kts b/build.gradle.kts index 04f37af..5f6dbb6 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -1,6 +1,4 @@ import java.time.Duration -import org.gradle.api.tasks.testing.logging.TestExceptionFormat -import org.gradle.external.javadoc.CoreJavadocOptions // These values come from gradle.properties val ossrhUsername: String by project @@ -13,16 +11,9 @@ buildscript { } } -plugins { - java - "java-library" - checkstyle - signing - "maven-publish" - idea - jacoco - id("de.marcphilipp.nexus-publish") version "0.3.0" - id("io.codearte.nexus-staging") version "0.30.0" +plugins { // see Dependencies.kt in buildSrc + Libs.javaBuiltInGradlePlugins.forEach { id(it) } + Libs.javaExtGradlePlugins.forEach { (n, v) -> id(n) version v } } repositories { @@ -32,11 +23,30 @@ repositories { mavenCentral() } -apply { from("build-shared.gradle") } +configurations.all { + // check for updates every build for dependencies with: 'changing: true' + resolutionStrategy.cacheChangingModulesFor(0, "seconds") +} + +base { + group = ProjectValues.groupId + archivesBaseName = ProjectValues.artifactId + version = version +} java { withJavadocJar() withSourcesJar() + sourceCompatibility = JavaVersion.VERSION_1_7 + targetCompatibility = JavaVersion.VERSION_1_7 +} + +// See Dependencies.kt in buildSrc for the purpose of "privateImplementation" +val privateImplementation by configurations.creating + +dependencies { // see Dependencies.kt in buildSrc + Libs.privateImplementation.forEach { privateImplementation(it)} + Libs.javaTestImplementation.forEach { testImplementation(it) } } checkstyle { @@ -44,120 +54,28 @@ checkstyle { } tasks.compileJava { - // See note in build-shared.gradle on the purpose of "privateImplementation" - classpath = configurations["privateImplementation"] -} - -tasks.javadoc.configure { - // Force the Javadoc build to fail if there are any Javadoc warnings. See: https://discuss.gradle.org/t/javadoc-fail-on-warning/18141/3 - // See JDK-8200363 (https://bugs.openjdk.java.net/browse/JDK-8200363) - // for information about the -Xwerror option. - (options as CoreJavadocOptions).addStringOption("Xwerror") - - // See note in build-shared.gradle on the purpose of "privateImplementation" + // See note in Dependencies.kt in buildSrc on "privateImplementation" classpath = configurations["privateImplementation"] } -tasks.test.configure { - testLogging { - events("passed", "skipped", "failed", "standardOut", "standardError") - showStandardStreams = true - exceptionFormat = TestExceptionFormat.FULL - } -} - -tasks.jacocoTestReport.configure { - reports { - xml.isEnabled = true - csv.isEnabled = true - html.isEnabled = true - } -} +helpers.Javadoc.configureTask(tasks.javadoc, configurations["privateImplementation"]) // see Javadoc.kt in buildSrc -tasks.jacocoTestCoverageVerification.configure { - // See notes in CONTRIBUTING.md on code coverage. Unfortunately we can't configure line-by-line code - // coverage overrides within the source code itself, because Jacoco operates on bytecode. - violationRules { - val knownMissedLinesForMethods = mapOf( - "EvaluationReason.error(com.launchdarkly.sdk.EvaluationReason.ErrorKind)" to 1, - "EvaluationReasonTypeAdapter.parse(com.google.gson.stream.JsonReader)" to 1, - "LDValue.equals(java.lang.Object)" to 1, - "LDValueTypeAdapter.read(com.google.gson.stream.JsonReader)" to 1, - "json.JsonSerialization.getDeserializableClasses()" to -1, - "json.LDGson.LDTypeAdapter.write(com.google.gson.stream.JsonWriter, java.lang.Object)" to 1, - "json.LDJackson.GsonReaderToJacksonParserAdapter.peekInternal()" to 3 - ) - - knownMissedLinesForMethods.forEach { (signature, maxMissedLines) -> - if (maxMissedLines > 0) { // < 0 means skip entire method - rule { - element = "METHOD" - includes = listOf("com.launchdarkly.sdk." + signature) - limit { - counter = "LINE" - value = "MISSEDCOUNT" - maximum = maxMissedLines.toBigDecimal() - } - } - } - } - - // General rule that we should expect 100% test coverage; exclude any methods that have overrides above - rule { - element = "METHOD" - limit { - counter = "LINE" - value = "MISSEDCOUNT" - maximum = 0.toBigDecimal() - } - excludes = knownMissedLinesForMethods.map { (signature, maxMissedLines) -> - "com.launchdarkly.sdk." + signature } - } - } -} +helpers.Test.configureTask(tasks.compileTestJava, tasks.test, + configurations["privateImplementation"]) // see Test.kt in buildSrc -idea { - module { - isDownloadJavadoc = true - isDownloadSources = true - } -} +helpers.Jacoco.configureTasks( // see Jacoco.kt in buildSrc + tasks.jacocoTestReport, + tasks.jacocoTestCoverageVerification +) -nexusStaging { - packageGroup = "com.launchdarkly" - numberOfRetries = 40 // we've seen extremely long delays in closing repositories -} +helpers.Idea.configure(idea) publishing { publications { create("mavenJava") { from(components["java"]) - groupId = "com.launchdarkly" - artifactId = "launchdarkly-java-sdk-common" - - pom { - name.set("launchdarkly-java-sdk-common") - description.set("LaunchDarkly SDK Java Common Classes") - url.set("https://github.com/launchdarkly/java-sdk-common") - licenses { - license { - name.set("The Apache License, Version 2.0") - url.set("http://www.apache.org/licenses/LICENSE-2.0.txt") - } - } - developers { - developer { - name.set("LaunchDarkly") - email.set("team@launchdarkly.com") - } - } - scm { - connection.set("scm:git:git://github.com/launchdarkly/java-sdk-common.git") - developerConnection.set("scm:git:ssh:git@github.com:launchdarkly/java-sdk-common.git") - url.set("https://github.com/launchdarkly/java-sdk-common") - } - } + helpers.Pom.standardPom(pom) // see Pom.kt in buildSrc } } repositories { @@ -165,6 +83,11 @@ publishing { } } +nexusStaging { + packageGroup = ProjectValues.groupId + numberOfRetries = 40 // we've seen extremely long delays in closing repositories +} + nexusPublishing { clientTimeout.set(Duration.ofMinutes(2)) // we've seen extremely long delays in creating repositories repositories { diff --git a/buildSrc/build.gradle.kts b/buildSrc/build.gradle.kts new file mode 100644 index 0000000..a0a9171 --- /dev/null +++ b/buildSrc/build.gradle.kts @@ -0,0 +1,20 @@ + +// This build script controls the building of the shared Gradle code in +// buildSrc. Putting code under buildSrc allows us to break it up for better +// clarity, leaving a much simpler build script at the top level of the repo. + +// For the java-sdk-common project, this also allows us to share some values +// between build.gradle.kts and build-android.gradle in a clearer way than +// the old method of including a shared build script. + +// Things that are specific to this project, like dependencies, are in +// buildSrc/src/main/kotlin. Reusable helper code that isn't specific to this +// project is in buildSrc/src/main/kotlin/helpers. + +plugins { + `kotlin-dsl` +} + +repositories { + jcenter() +} diff --git a/buildSrc/src/main/kotlin/Dependencies.kt b/buildSrc/src/main/kotlin/Dependencies.kt new file mode 100644 index 0000000..153a00d --- /dev/null +++ b/buildSrc/src/main/kotlin/Dependencies.kt @@ -0,0 +1,67 @@ + +// Centralize dependencies here instead of writing them out in the top-level +// build script(s). + +object Versions { + const val gson = "2.8.9" + const val jacksonCore = "2.10.5" + const val jacksonDatabind = "2.10.5.1" +} + +object PluginVersions { + const val nexusPublish = "0.3.0" + const val nexusStaging = "0.30.0" +} + +object Libs { + val implementation = listOf( + // We would put anything here that we want to go into the Gradle "implementation" + // configuration, if and only if we want those things to show up in pom.xml. + ) + + val javaTestImplementation = listOf( + "org.hamcrest:hamcrest-library:1.3", + "junit:junit:4.12" + ) + + val androidTestImplementation = javaTestImplementation + listOf( + "com.android.support.test:runner:1.0.2" + ) + + val privateImplementation = listOf( + // These will be used in the compile-time classpath, but they should *not* be put in + // the usual Gradle "implementation" configuration, because we don't want them to be + // visible at all in the module's published dependencies - not even in "runtime" scope. + // Here's why: + // + // 1. For Gson: While java-sdk-common does need Gson in order to work, the + // LaunchDarkly SDKs that use java-sdk-common have different strategies for packaging + // Gson. The Android SDK exposes it as a regular dependency; the Java server-side SDK + // embeds and shades Gson and does not expose it as a dependency. So we are leaving + // it up to the SDK to provide Gson in some way. + // + // 2. For Jackson: The SDKs do not use, require, or embed Jackson; we provide the + // LDJackson class as a convenience for applications that do use Jackson, and it is + // only usable if the application already has Jackson in its classpath. So we do not + // want Jackson to show up as a transitive dependency. + + "com.google.code.gson:gson:${Versions.gson}", + "com.fasterxml.jackson.core:jackson-core:${Versions.jacksonCore}", + "com.fasterxml.jackson.core:jackson-databind:${Versions.jacksonDatabind}" + ) + + val javaBuiltInGradlePlugins = listOf( + "java", + "java-library", + "checkstyle", + "signing", + "maven-publish", + "idea", + "jacoco" + ) + + val javaExtGradlePlugins = mapOf( + "de.marcphilipp.nexus-publish" to PluginVersions.nexusPublish, + "io.codearte.nexus-staging" to PluginVersions.nexusStaging + ) +} diff --git a/buildSrc/src/main/kotlin/ProjectValues.kt b/buildSrc/src/main/kotlin/ProjectValues.kt new file mode 100644 index 0000000..55fcda8 --- /dev/null +++ b/buildSrc/src/main/kotlin/ProjectValues.kt @@ -0,0 +1,15 @@ + +// This file defines basic properties of the project that are used in the +// build script and the helper code. + +object ProjectValues { + const val groupId = "com.launchdarkly" + const val artifactId = "launchdarkly-java-sdk-common" + const val description = "LaunchDarkly SDK Java Common Classes" + const val githubRepo = "launchdarkly/java-sdk-common" + + const val sdkBasePackage = "com.launchdarkly.sdk" + + const val pomDeveloperName = "LaunchDarkly SDK Team" + const val pomDeveloperEmail = "sdks@launchdarkly.com" +} diff --git a/buildSrc/src/main/kotlin/TestCoverageOverrides.kt b/buildSrc/src/main/kotlin/TestCoverageOverrides.kt new file mode 100644 index 0000000..8014382 --- /dev/null +++ b/buildSrc/src/main/kotlin/TestCoverageOverrides.kt @@ -0,0 +1,29 @@ + +// See notes in CONTRIBUTING.md on code coverage. Unfortunately we can't configure +// line-by-line code coverage overrides within the source code itself, because Jacoco +// operates on bytecode. + +// These values are used by helpers/Jacoco.kt. + +object TestCoverageOverrides { + val prefixForAllMethodSignatures = ProjectValues.sdkBasePackage + "." + + // Each entry in methodsWithMissedLineCount is an override to tell the Jacoco plugin + // that we're aware of a gap in our test coverage and are OK with it. In each entry, + // the key is the method signature and the value is the number of lines that we + // expect Jacoco to report as missed. + val methodsWithMissedLineCount = mapOf( + "EvaluationReason.error(com.launchdarkly.sdk.EvaluationReason.ErrorKind)" to 1, + "EvaluationReasonTypeAdapter.parse(com.google.gson.stream.JsonReader)" to 1, + "LDValue.equals(java.lang.Object)" to 1, + "LDValueTypeAdapter.read(com.google.gson.stream.JsonReader)" to 1, + "json.LDGson.LDTypeAdapter.write(com.google.gson.stream.JsonWriter, java.lang.Object)" to 1, + "json.LDJackson.GsonReaderToJacksonParserAdapter.peekInternal()" to 3 + ).mapKeys { prefixForAllMethodSignatures + it.key } + + // Each entry in methodsToSkip is an override to tell the Jacoco plugin to ignore + // code coverage in the method with the specified signature. + val methodsToSkip = listOf( + "json.JsonSerialization.getDeserializableClasses()" + ).map { prefixForAllMethodSignatures + it } +} diff --git a/buildSrc/src/main/kotlin/helpers/Idea.kt b/buildSrc/src/main/kotlin/helpers/Idea.kt new file mode 100644 index 0000000..c2f85d5 --- /dev/null +++ b/buildSrc/src/main/kotlin/helpers/Idea.kt @@ -0,0 +1,16 @@ +package helpers + +import org.gradle.api.tasks.TaskProvider +import org.gradle.plugins.ide.idea.model.IdeaModel + +// Idea.configure provides reusable configuration logic for the Idea +// behavior we normally use. + +object Idea { + fun configure(ideaModel: IdeaModel) { + ideaModel.module { + isDownloadJavadoc = true + isDownloadSources = true + } + } +} diff --git a/buildSrc/src/main/kotlin/helpers/Jacoco.kt b/buildSrc/src/main/kotlin/helpers/Jacoco.kt new file mode 100644 index 0000000..77f6c87 --- /dev/null +++ b/buildSrc/src/main/kotlin/helpers/Jacoco.kt @@ -0,0 +1,52 @@ +package helpers + +import org.gradle.api.tasks.TaskProvider +import org.gradle.testing.jacoco.tasks.JacocoReport +import org.gradle.testing.jacoco.tasks.JacocoCoverageVerification + +// Jacoco.configureTasks provides reusable configuration logic for using the Jacoco +// test coverage plugin in a Java project. See also: TestCoverageOverrides.kt + +object Jacoco { + fun configureTasks(reportTask: TaskProvider, + verificationTask: TaskProvider) { + reportTask.configure { + reports { + xml.isEnabled = true + csv.isEnabled = true + html.isEnabled = true + } + } + + verificationTask.configure { + // See notes in CONTRIBUTING.md on code coverage. Unfortunately we can't configure line-by-line code + // coverage overrides within the source code itself, because Jacoco operates on bytecode. + violationRules { + TestCoverageOverrides.methodsWithMissedLineCount.forEach { signature, maxMissedLines -> + rule { + element = "METHOD" + includes = listOf(signature) + limit { + counter = "LINE" + value = "MISSEDCOUNT" + maximum = maxMissedLines.toBigDecimal() + } + } + } + + // General rule that we should expect 100% test coverage; exclude any methods that + // have overrides in TestCoverageOverrides. + rule { + element = "METHOD" + limit { + counter = "LINE" + value = "MISSEDCOUNT" + maximum = 0.toBigDecimal() + } + excludes = TestCoverageOverrides.methodsWithMissedLineCount.map { it.key } + + TestCoverageOverrides.methodsToSkip + } + } + } + } +} diff --git a/buildSrc/src/main/kotlin/helpers/Javadoc.kt b/buildSrc/src/main/kotlin/helpers/Javadoc.kt new file mode 100644 index 0000000..2549ebc --- /dev/null +++ b/buildSrc/src/main/kotlin/helpers/Javadoc.kt @@ -0,0 +1,21 @@ +package helpers + +import org.gradle.api.artifacts.Configuration +import org.gradle.api.tasks.TaskProvider +import org.gradle.api.tasks.javadoc.Javadoc +import org.gradle.external.javadoc.CoreJavadocOptions + +object Javadoc { + fun configureTask(javadocTask: TaskProvider, classpathConfig: Configuration?) { + javadocTask.configure { + // Force the Javadoc build to fail if there are any Javadoc warnings. See: https://discuss.gradle.org/t/javadoc-fail-on-warning/18141/3 + // See JDK-8200363 (https://bugs.openjdk.java.net/browse/JDK-8200363) + // for information about the -Xwerror option. + (options as CoreJavadocOptions).addStringOption("Xwerror") + + if (classpathConfig != null) { + classpath += classpathConfig + } + } + } +} diff --git a/buildSrc/src/main/kotlin/helpers/Pom.kt b/buildSrc/src/main/kotlin/helpers/Pom.kt new file mode 100644 index 0000000..ac9906e --- /dev/null +++ b/buildSrc/src/main/kotlin/helpers/Pom.kt @@ -0,0 +1,31 @@ +package helpers + +import org.gradle.api.publish.maven.MavenPom + +// Pom.standardPom provides reusable logic for setting the pom.xml properties +// of LaunchDarkly packages. It gets its values from ProjectValues.kt. + +object Pom { + fun standardPom(pom: MavenPom) { + pom.name.set(ProjectValues.artifactId) + pom.description.set(ProjectValues.description) + pom.url.set("https://github.com/${ProjectValues.githubRepo}") + pom.licenses { + license { + url.set("http://www.apache.org/licenses/LICENSE-2.0.txt") + name.set("The Apache License, Version 2.0") + } + } + pom.developers { + developer { + name.set(ProjectValues.pomDeveloperName) + email.set(ProjectValues.pomDeveloperEmail) + } + } + pom.scm { + connection.set("scm:git:git://github.com/${ProjectValues.githubRepo}.git") + developerConnection.set("scm:git:ssh:git@github.com:${ProjectValues.githubRepo}.git") + url.set("https://github.com/${ProjectValues.githubRepo}") + } + } +} diff --git a/buildSrc/src/main/kotlin/helpers/Test.kt b/buildSrc/src/main/kotlin/helpers/Test.kt new file mode 100644 index 0000000..c213db5 --- /dev/null +++ b/buildSrc/src/main/kotlin/helpers/Test.kt @@ -0,0 +1,34 @@ +package helpers + +import org.gradle.api.artifacts.Configuration +import org.gradle.api.tasks.TaskProvider +import org.gradle.api.tasks.compile.JavaCompile +import org.gradle.api.tasks.testing.Test +import org.gradle.api.tasks.testing.logging.TestExceptionFormat + +// Test.configureTask provides reusable configuration logic for the Java test +// behavior we normally use. + +object Test { + fun configureTask(compileTestTask: TaskProvider, testTask: TaskProvider, + classpathConfig: Configuration?) { + + compileTestTask.configure { + if (classpathConfig != null) { + classpath += classpathConfig + } + } + + testTask.configure { + testLogging { + events("passed", "skipped", "failed", "standardOut", "standardError") + showStandardStreams = true + exceptionFormat = TestExceptionFormat.FULL + } + + if (classpathConfig != null) { + classpath += classpathConfig + } + } + } +} diff --git a/settings.gradle b/settings.gradle deleted file mode 100644 index a9e03eb..0000000 --- a/settings.gradle +++ /dev/null @@ -1 +0,0 @@ -rootProject.name = 'launchdarkly-java-sdk-common' diff --git a/settings.gradle.kts b/settings.gradle.kts new file mode 100644 index 0000000..fbd2f48 --- /dev/null +++ b/settings.gradle.kts @@ -0,0 +1 @@ +rootProject.name = "launchdarkly-java-sdk-common" diff --git a/src/main/java/com/launchdarkly/sdk/LDUser.java b/src/main/java/com/launchdarkly/sdk/LDUser.java index 11d7942..234f12b 100644 --- a/src/main/java/com/launchdarkly/sdk/LDUser.java +++ b/src/main/java/com/launchdarkly/sdk/LDUser.java @@ -23,8 +23,8 @@ * optional. You may also define custom properties with arbitrary names and values. *

* For a fuller description of user attributes and how they can be referenced in feature flag rules, see the reference - * guides on Setting user attributes - * and Targeting users. + * guides on Setting user attributes + * and Targeting users. *

* LaunchDarkly defines a standard JSON encoding for user objects, used by the JavaScript SDK and also in analytics * events. {@link LDUser} can be converted to and from JSON in any of these ways: @@ -340,7 +340,7 @@ public Builder privateIp(String s) { /** * Sets the secondary key for a user. This affects - * feature flag targeting + * feature flag targeting * as follows: if you have chosen to bucket users by a specific attribute, the secondary key (if set) * is used to further distinguish between users who are otherwise identical according to that attribute. * @param s the secondary key for the user @@ -516,7 +516,7 @@ public Builder privateEmail(String email) { /** * Adds a {@link java.lang.String}-valued custom attribute. When set to one of the - * built-in + * built-in * user attribute keys, this custom attribute will be ignored. * * @param k the key for the custom attribute @@ -529,7 +529,7 @@ public Builder custom(String k, String v) { /** * Adds an integer-valued custom attribute. When set to one of the - * built-in + * built-in * user attribute keys, this custom attribute will be ignored. * * @param k the key for the custom attribute @@ -542,7 +542,7 @@ public Builder custom(String k, int n) { /** * Adds a double-precision numeric custom attribute. When set to one of the - * built-in + * built-in * user attribute keys, this custom attribute will be ignored. * * @param k the key for the custom attribute @@ -555,7 +555,7 @@ public Builder custom(String k, double n) { /** * Add a boolean-valued custom attribute. When set to one of the - * built-in + * built-in * user attribute keys, this custom attribute will be ignored. * * @param k the key for the custom attribute @@ -568,7 +568,7 @@ public Builder custom(String k, boolean b) { /** * Add a custom attribute whose value can be any JSON type, using {@link LDValue}. When set to one of the - * built-in + * built-in * user attribute keys, this custom attribute will be ignored. * * @param k the key for the custom attribute @@ -593,7 +593,7 @@ private Builder customInternal(UserAttribute a, LDValue v) { /** * Add a {@link java.lang.String}-valued custom attribute that will not be sent back to LaunchDarkly. * When set to one of the - * built-in + * built-in * user attribute keys, this custom attribute will be ignored. * * @param k the key for the custom attribute @@ -607,7 +607,7 @@ public Builder privateCustom(String k, String v) { /** * Add an int-valued custom attribute that will not be sent back to LaunchDarkly. * When set to one of the - * built-in + * built-in * user attribute keys, this custom attribute will be ignored. * * @param k the key for the custom attribute @@ -621,7 +621,7 @@ public Builder privateCustom(String k, int n) { /** * Add a double-precision numeric custom attribute that will not be sent back to LaunchDarkly. * When set to one of the - * built-in + * built-in * user attribute keys, this custom attribute will be ignored. * * @param k the key for the custom attribute @@ -635,7 +635,7 @@ public Builder privateCustom(String k, double n) { /** * Add a boolean-valued custom attribute that will not be sent back to LaunchDarkly. * When set to one of the - * built-in + * built-in * user attribute keys, this custom attribute will be ignored. * * @param k the key for the custom attribute @@ -649,7 +649,7 @@ public Builder privateCustom(String k, boolean b) { /** * Add a custom attribute of any JSON type, that will not be sent back to LaunchDarkly. * When set to one of the - * built-in + * built-in * user attribute keys, this custom attribute will be ignored. * * @param k the key for the custom attribute diff --git a/src/main/java/com/launchdarkly/sdk/UserAttribute.java b/src/main/java/com/launchdarkly/sdk/UserAttribute.java index 6514851..f8fb8ec 100644 --- a/src/main/java/com/launchdarkly/sdk/UserAttribute.java +++ b/src/main/java/com/launchdarkly/sdk/UserAttribute.java @@ -18,8 +18,8 @@ * always reuse the same instances. *

* For a fuller description of user attributes and how they can be referenced in feature flag rules, see the reference - * guides on Setting user attributes - * and Targeting users. + * guides on Setting user attributes + * and Targeting users. */ @JsonAdapter(UserAttribute.UserAttributeTypeAdapter.class) public final class UserAttribute implements JsonSerializable {