From 3f669d2b2d4cce50deb700efec5fb4ef3900ff50 Mon Sep 17 00:00:00 2001 From: Brian Wernick Date: Sun, 24 May 2026 20:04:18 -0600 Subject: [PATCH] Migrated groovy scripts to kts --- .editorconfig | 4 +- README.md | 2 +- build.gradle | 55 ------- build.gradle.kts | 49 +++++++ buildSrc/build.gradle.kts | 8 ++ .../libraryInfo.properties | 0 .../src/main/kotlin/release/Dependencies.kt | 47 ++++++ .../src/main/kotlin/release/LibraryInfo.kt | 15 ++ .../main/kotlin/release/PublicationManager.kt | 74 ++++++++++ .../src/main/kotlin/release/ReleaseInfo.kt | 38 +++++ .../src/main/kotlin/util/ProjectConfig.kt | 12 ++ buildSrc/src/main/kotlin/util/TestOutput.kt | 135 ++++++++++++++++++ demo/build.gradle | 57 -------- demo/build.gradle.kts | 56 ++++++++ gradle.properties | 14 +- gradle/libs.versions.toml | 4 +- gradle/release/libraryInfo.gradle | 43 ------ gradle/release/publish.gradle | 123 ---------------- gradle/util/testOutput.gradle | 80 ----------- gradle/wrapper/gradle-wrapper.properties | 2 +- library/build.gradle | 58 -------- library/build.gradle.kts | 114 +++++++++++++++ settings.gradle | 9 -- settings.gradle.kts | 18 +++ 24 files changed, 573 insertions(+), 444 deletions(-) delete mode 100644 build.gradle create mode 100644 build.gradle.kts create mode 100644 buildSrc/build.gradle.kts rename libraryInfo.properties => buildSrc/libraryInfo.properties (100%) create mode 100644 buildSrc/src/main/kotlin/release/Dependencies.kt create mode 100644 buildSrc/src/main/kotlin/release/LibraryInfo.kt create mode 100644 buildSrc/src/main/kotlin/release/PublicationManager.kt create mode 100644 buildSrc/src/main/kotlin/release/ReleaseInfo.kt create mode 100644 buildSrc/src/main/kotlin/util/ProjectConfig.kt create mode 100644 buildSrc/src/main/kotlin/util/TestOutput.kt delete mode 100644 demo/build.gradle create mode 100644 demo/build.gradle.kts delete mode 100644 gradle/release/libraryInfo.gradle delete mode 100644 gradle/release/publish.gradle delete mode 100644 gradle/util/testOutput.gradle delete mode 100644 library/build.gradle create mode 100644 library/build.gradle.kts delete mode 100644 settings.gradle create mode 100644 settings.gradle.kts diff --git a/.editorconfig b/.editorconfig index d4eded2..8f6419c 100644 --- a/.editorconfig +++ b/.editorconfig @@ -1,4 +1,4 @@ [*] -indent_size = 2 +indent_size = 4 indent_style = space -tab_width = 2 \ No newline at end of file +tab_width = 4 \ No newline at end of file diff --git a/README.md b/README.md index 4fe6a6b..5278d54 100644 --- a/README.md +++ b/README.md @@ -38,7 +38,7 @@ val userColorFlow = dataStore.flow("userColor", Color.valueOf(0xFFFFFFFF), Color License ------- - Copyright 2023 DataStore Delegates Contributors + Copyright 2026 DataStore Delegates Contributors Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/build.gradle b/build.gradle deleted file mode 100644 index 73a2d47..0000000 --- a/build.gradle +++ /dev/null @@ -1,55 +0,0 @@ -buildscript { - repositories { - mavenCentral() - google() - } - - dependencies { - classpath libs.android.gradle - classpath libs.kotlin.gradle - } -} - -plugins { - alias libs.plugins.android.application apply false - alias libs.plugins.android.library apply false - alias libs.plugins.compose.compiler apply false - alias libs.plugins.kotlin.android apply false - alias libs.plugins.nexus.publish -} - -apply from: './gradle/util/testOutput.gradle' - -allprojects { - repositories { - mavenCentral() - google() - } -} - -/* - * Below is the functionality to publish the `library` module to Maven Central (Sonatype) using the - * plugin `io.github.gradle-nexus.publish-plugin`. This functionality is included in this (root) - * `build.gradle` because that's what the plugin expects; if this changes in the future then we - * should migrate this functionality into the `publish.gradle` file instead. - */ -apply from: 'gradle/release/libraryInfo.gradle' - -ext { - libraryInfo = getLibraryInfo() -} - -// Used by the publish-plugin -group = libraryInfo.groupId -version = libraryInfo.versionName - -nexusPublishing { - repositories { - sonatype { - nexusUrl.set(uri("https://s01.oss.sonatype.org/service/local/")) - snapshotRepositoryUrl.set(uri("https://s01.oss.sonatype.org/content/repositories/snapshots/")) - username = System.getenv("SONATYPE_TOKEN_USERNAME") - password = System.getenv("SONATYPE_TOKEN_PASSWORD") - } - } -} \ No newline at end of file diff --git a/build.gradle.kts b/build.gradle.kts new file mode 100644 index 0000000..772e732 --- /dev/null +++ b/build.gradle.kts @@ -0,0 +1,49 @@ +import util.TestOutput + +buildscript { + repositories { + mavenCentral() + google() + } + + dependencies { + classpath(libs.android.gradle) + classpath(libs.kotlin.gradle) + } +} + +plugins { + alias(libs.plugins.android.application) apply false + alias(libs.plugins.android.library) apply false + alias(libs.plugins.compose.compiler) apply false + alias(libs.plugins.dokka) apply false + alias(libs.plugins.nexus.publish) +} + +allprojects { + repositories { + mavenCentral() + google() + } + + tasks.withType(Test::class).configureEach { + TestOutput.configure(this) + } +} + +/* + * Below is the functionality to publish the `library` module to Maven Central (Sonatype) using the + * plugin `io.github.gradle-nexus.publish-plugin`. This functionality is included in this (root) + * `build.gradle` because that's what the plugin expects; if this changes in the future then we + * should migrate this functionality into the `publish.gradle` file instead. + */ +nexusPublishing { + repositories { + sonatype { + nexusUrl.set(uri("https://s01.oss.sonatype.org/service/local/")) + snapshotRepositoryUrl.set(uri("https://s01.oss.sonatype.org/content/repositories/snapshots/")) + username = System.getenv("SONATYPE_TOKEN_USERNAME") + password = System.getenv("SONATYPE_TOKEN_PASSWORD") + } + } +} \ No newline at end of file diff --git a/buildSrc/build.gradle.kts b/buildSrc/build.gradle.kts new file mode 100644 index 0000000..d555147 --- /dev/null +++ b/buildSrc/build.gradle.kts @@ -0,0 +1,8 @@ +plugins { + `kotlin-dsl` +} + +repositories { + google() + mavenCentral() +} diff --git a/libraryInfo.properties b/buildSrc/libraryInfo.properties similarity index 100% rename from libraryInfo.properties rename to buildSrc/libraryInfo.properties diff --git a/buildSrc/src/main/kotlin/release/Dependencies.kt b/buildSrc/src/main/kotlin/release/Dependencies.kt new file mode 100644 index 0000000..027deab --- /dev/null +++ b/buildSrc/src/main/kotlin/release/Dependencies.kt @@ -0,0 +1,47 @@ +package release + +import groovy.util.Node +import org.gradle.api.artifacts.ConfigurationContainer +import org.gradle.api.artifacts.Dependency +import org.gradle.kotlin.dsl.get + +object Dependencies { + + fun appendAll( + node: Node, + configurations: ConfigurationContainer, + ) { + configurations["api"].dependencies.forEach { dependency -> + append( + dependency = dependency, + node = node, + scope = "compile" + ) + } + + configurations["implementation"].dependencies.forEach { dependency -> + append( + dependency = dependency, + node = node, + scope = "runtime" + ) + } + } + + private fun append( + dependency: Dependency, + node: Node, + scope: String + ) { + if (dependency.name == "unspecified" || dependency.group == null || dependency.version == null) { + return + } + + with(node.appendNode("dependency")) { + appendNode("groupId", dependency.group) + appendNode("artifactId", dependency.name) + appendNode("version", dependency.version) + appendNode("scope", scope) + } + } +} \ No newline at end of file diff --git a/buildSrc/src/main/kotlin/release/LibraryInfo.kt b/buildSrc/src/main/kotlin/release/LibraryInfo.kt new file mode 100644 index 0000000..3b2a467 --- /dev/null +++ b/buildSrc/src/main/kotlin/release/LibraryInfo.kt @@ -0,0 +1,15 @@ +package release + +data class LibraryInfo( + val artifactId: String, + val groupId: String, + val version: Version, +) { + data class Version( + val major: Int, + val minor: Int, + val patch: Int, + ) { + val name = "${major}.${minor}.${patch}" + } +} \ No newline at end of file diff --git a/buildSrc/src/main/kotlin/release/PublicationManager.kt b/buildSrc/src/main/kotlin/release/PublicationManager.kt new file mode 100644 index 0000000..3a77e1b --- /dev/null +++ b/buildSrc/src/main/kotlin/release/PublicationManager.kt @@ -0,0 +1,74 @@ +package release + +import org.gradle.api.Project +import org.gradle.api.publish.maven.MavenPom +import org.gradle.api.publish.maven.MavenPublication + +object PublicationManager { + @JvmStatic + fun configure( + project: Project, + publication: MavenPublication, + vararg artifacts: Any, + ) { + val libraryInfo = ReleaseInfo.getLibraryInfo(project) + + project.group = libraryInfo.groupId + project.version = libraryInfo.version.name + + publication.apply { + groupId = libraryInfo.groupId + artifactId = libraryInfo.artifactId + version = libraryInfo.version.name + + setArtifacts(artifacts.asIterable()) + + pom { + configure( + libraryInfo = libraryInfo, + project = project + ) + } + } + } + + private fun MavenPom.configure( + libraryInfo: LibraryInfo, + project: Project, + ) { + description?.set("Property Delegation for the AndroidX DataStore") + name?.set(libraryInfo.groupId + ":" + libraryInfo.artifactId) + url?.set("https://github.com/brianwernick/DataStoreDelegates") + + developers { + developer { + name?.set("Brian Wernick") + email?.set("brian@devbrackets.com") + organization?.set("DevBrackets") + organizationUrl?.set("https://devbrackets.com") + } + } + + licenses { + license { + name?.set("The Apache License, Version 2.0") + url?.set("http://www.apache.org/licenses/LICENSE-2.0.txt") + } + } + + scm { + connection?.set("scm:git:github.com/brianwernick/DataStoreDelegates.git") + developerConnection?.set("scm:git:ssh://github.com/brianwernick/DataStoreDelegates.git") + url?.set("https://github.com/brianwernick/DataStoreDelegates/tree/main") + } + + // The generated POM doesn't include dependencies for Android artifacts, + // so we manually add them here + withXml { + Dependencies.appendAll( + node = asNode().appendNode("dependencies"), + configurations = project.configurations + ) + } + } +} \ No newline at end of file diff --git a/buildSrc/src/main/kotlin/release/ReleaseInfo.kt b/buildSrc/src/main/kotlin/release/ReleaseInfo.kt new file mode 100644 index 0000000..2af2f92 --- /dev/null +++ b/buildSrc/src/main/kotlin/release/ReleaseInfo.kt @@ -0,0 +1,38 @@ +package release + +import org.gradle.api.Project +import java.io.File +import java.util.Properties + +object ReleaseInfo { + private const val KEY_ARTIFACT_ID = "ARTIFACT_ID" + private const val KEY_GROUP_ID = "GROUP_ID" + + private const val KEY_VERSION_MAJOR = "VERSION_MAJOR" + private const val KEY_VERSION_MINOR = "VERSION_MINOR" + private const val KEY_VERSION_PATCH = "VERSION_PATCH" + + fun getLibraryInfo(project: Project): LibraryInfo { + val properties = readProperties(project) + + val version = LibraryInfo.Version( + major = properties[KEY_VERSION_MAJOR].toString().toInt(), + minor = properties[KEY_VERSION_MINOR].toString().toInt(), + patch = properties[KEY_VERSION_PATCH].toString().toInt() + ) + + return LibraryInfo( + artifactId = properties[KEY_ARTIFACT_ID].toString(), + groupId = properties[KEY_GROUP_ID].toString(), + version = version + ) + } + + private fun readProperties(project: Project): Properties { + val file = File("${project.rootDir}/buildSrc/libraryInfo.properties") + + return Properties().apply { + load(file.inputStream()) + } + } +} \ No newline at end of file diff --git a/buildSrc/src/main/kotlin/util/ProjectConfig.kt b/buildSrc/src/main/kotlin/util/ProjectConfig.kt new file mode 100644 index 0000000..8050bd3 --- /dev/null +++ b/buildSrc/src/main/kotlin/util/ProjectConfig.kt @@ -0,0 +1,12 @@ +package util + +import org.gradle.api.JavaVersion + +@Suppress("ConstPropertyName") +object ProjectConfig { + const val compileSdk = 37 + const val minSdk = 23 + const val targetSdk = compileSdk + + val javaVersion = JavaVersion.VERSION_11 +} \ No newline at end of file diff --git a/buildSrc/src/main/kotlin/util/TestOutput.kt b/buildSrc/src/main/kotlin/util/TestOutput.kt new file mode 100644 index 0000000..66e4c84 --- /dev/null +++ b/buildSrc/src/main/kotlin/util/TestOutput.kt @@ -0,0 +1,135 @@ +package util + +import org.gradle.api.Project +import org.gradle.api.tasks.testing.AbstractTestTask +import org.gradle.api.tasks.testing.TestDescriptor +import org.gradle.api.tasks.testing.TestListener +import org.gradle.api.tasks.testing.TestResult +import org.gradle.internal.logging.text.StyledTextOutput.Style +import org.gradle.internal.logging.text.StyledTextOutputFactory +import org.gradle.kotlin.dsl.support.serviceOf + +/** + * Writes a simplified test result summary to the console, for each configured module, + * in the format: + * ``` + * ╔═ module-name ════════════════════════════╗ + * ║ 24 Total, 18 Passed, 6 Failed, 0 Skipped ║ + * ╚══════════════════════════════════════════╝ + * ``` + * + * To configure this for all modules, add the below code to the root `build.gradle.kts` + * ```kotlin + * allprojects { + * tasks.withType(Test::class).configureEach { + * TestOutput.configure(this) + * } + * } + * ``` + */ +object TestOutput { + fun configure(task: T) { + with(task) { + testLogging { + outputs.upToDateWhen { false } + events("failed", "skipped", "standardOut") + addTestListener(TestResultListener(task.project)) + } + } + } + + private fun printModuleResults( + title: String, + results: ResultSummary, + project: Project + ) { + val summaryItems = listOf( + "${results.total} Total", + "${results.passed} Passed", + "${results.failed} Failed", + "${results.skipped} Skipped" + ) + + val summary = summaryItems.joinToString( + separator = ", ", + prefix = " ", + postfix = " " + ) + + val style = when { + results.failed > 0 -> Style.Failure + results.skipped > 0 -> Style.Info + else -> Style.Success + } + + project.printTestResults( + title = " $title ", + summary = summary, + style = style + ) + } + + private fun Project.printTestResults( + title: String, + summary: String, + style: Style, + ) { + val maxWidth = maxOf(title.length, summary.length) + + val styleFactory = serviceOf() + val output = styleFactory.create("test-output").withStyle(style) + + output.apply { + println("╔═${title}${fill('═', length = maxWidth - title.length - 1)}╗") + println("║$summary${fill(' ', length = maxWidth - summary.length)}║") + println("╚${fill('═', length = maxWidth)}╝") + } + } + + private fun fill(char: Char, length: Int): String { + return buildString { + repeat(length) { + append(char) + } + } + } + + private data class ResultSummary( + val passed: Long, + val failed: Long, + val skipped: Long, + val total: Long + ) { + companion object { + fun forResult(result: TestResult): ResultSummary { + return ResultSummary( + passed = result.successfulTestCount, + failed = result.failedTestCount, + skipped = result.skippedTestCount, + total = result.testCount + ) + } + } + } + + private class TestResultListener(private val project: Project) : TestListener { + override fun beforeSuite(suite: TestDescriptor?) {} + override fun afterSuite(suite: TestDescriptor?, result: TestResult?) { + if (suite?.parent == null && result != null) { + // The displayName is in the format "project '{moduleName}'" + val nameRegex = """project '([a-zA-Z:]+)'""".toRegex() + val matchResult = nameRegex.find(project.displayName) + val moduleName = matchResult?.groupValues?.getOrNull(1) ?: project.displayName + + printModuleResults( + title = moduleName, + results = ResultSummary.forResult(result), + project = project + ) + } + } + + override fun beforeTest(testDescriptor: TestDescriptor?) {} + override fun afterTest(testDescriptor: TestDescriptor?, result: TestResult?) {} + } +} \ No newline at end of file diff --git a/demo/build.gradle b/demo/build.gradle deleted file mode 100644 index ad0d29b..0000000 --- a/demo/build.gradle +++ /dev/null @@ -1,57 +0,0 @@ -plugins { - alias libs.plugins.android.application - alias libs.plugins.kotlin.android - alias libs.plugins.compose.compiler -} - -dependencies { - implementation project(':library') - - // Misc - implementation libs.core.ktx - implementation libs.appcompat - - // Jetpack Compose UI - implementation libs.ui - implementation libs.ui.tooling - implementation libs.ui.tooling.preview - implementation libs.material - implementation libs.material.icons.core - implementation libs.activity.compose - implementation libs.navigation.compose -} - -android { - namespace 'com.devbrackets.android.datastoredemo' - compileSdk = 37 - - defaultConfig { - applicationId "com.devbrackets.android.datastoredemo" - minSdkVersion 23 - targetSdkVersion 37 - versionCode 1 - versionName "1.0.0" - } - - sourceSets { - main.java.srcDirs += "src/main/kotlin" - } - - buildFeatures { - compose true - viewBinding true - } - - compileOptions { - sourceCompatibility JavaVersion.VERSION_11 - targetCompatibility JavaVersion.VERSION_11 - } - - kotlinOptions { - jvmTarget = JavaVersion.VERSION_11 - } - - lint { - abortOnError false - } -} diff --git a/demo/build.gradle.kts b/demo/build.gradle.kts new file mode 100644 index 0000000..cad73e6 --- /dev/null +++ b/demo/build.gradle.kts @@ -0,0 +1,56 @@ +import util.ProjectConfig + +plugins { + alias(libs.plugins.android.application) + alias(libs.plugins.compose.compiler) +} + +dependencies { + implementation(project(":library")) + + // Misc + implementation(libs.core.ktx) + implementation(libs.appcompat) + + // Jetpack Compose UI + implementation(libs.ui) + implementation(libs.ui.tooling) + implementation(libs.ui.tooling.preview) + implementation(libs.material) + implementation(libs.material.icons.core) + implementation(libs.activity.compose) + implementation(libs.navigation.compose) +} + +android { + namespace = "com.devbrackets.android.datastoredemo" + + compileSdk = ProjectConfig.compileSdk + + defaultConfig { + applicationId = "com.devbrackets.android.datastoredemo" + minSdk = ProjectConfig.minSdk + targetSdk = ProjectConfig.targetSdk + versionCode = 1 + versionName = "1.0.0-demo" + } + + sourceSets { + getByName("main") { + kotlin.directories.add("src/main/kotlin") + } + } + + buildFeatures { + compose = true + } + + compileOptions { + sourceCompatibility = ProjectConfig.javaVersion + targetCompatibility = ProjectConfig.javaVersion + } + + lint { + abortOnError = false + } +} diff --git a/gradle.properties b/gradle.properties index fa9c9a8..5d539d6 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,15 +1,3 @@ -android.builtInKotlin=false -android.defaults.buildfeatures.resvalues=true android.dependency.useConstraints=true -android.enableAppCompileTimeRClass=false -android.enableJetifier=true -android.newDsl=false -android.nonFinalResIds=false android.nonTransitiveRClass=false -android.r8.optimizedResourceShrinking=false -android.r8.strictFullModeForKeepRules=false -android.sdk.defaultTargetSdkToCompileSdkIfUnset=false -android.uniquePackageNames=false -android.useAndroidX=true -android.usesSdkInManifest.disallowed=false -org.gradle.jvmargs=-Xms512m +org.gradle.jvmargs=-Xms512m \ No newline at end of file diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 3a335b7..bcb17fa 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -19,7 +19,7 @@ core-ktx = { module = "androidx.core:core-ktx", version.ref = "coreKtx" } datastore-preferences = { module = "androidx.datastore:datastore-preferences", version.ref = "datastorePreferences" } junit = { module = "junit:junit", version.ref = "junit" } kotlin-gradle = { module = "org.jetbrains.kotlin:kotlin-gradle-plugin", version.ref = "kotlin" } -kotlin-stdlib-jdk7 = { module = "org.jetbrains.kotlin:kotlin-stdlib-jdk7", version.ref = "kotlin" } +kotlin-stdlib = { module = "org.jetbrains.kotlin:kotlin-stdlib", version.ref = "kotlin" } material = { module = "androidx.compose.material:material", version = "1.11.2" } material-icons-core = { module = "androidx.compose.material:material-icons-core", version = "1.7.8" } navigation-compose = { module = "androidx.navigation:navigation-compose", version.ref = "navigationCompose" } @@ -32,7 +32,7 @@ ui-tooling-preview = { module = "androidx.compose.ui:ui-tooling-preview", versio android-application = { id = "com.android.application", version.ref = "androidGradlePlugin" } android-library = { id = "com.android.library", version.ref = "androidGradlePlugin" } compose-compiler = { id = "org.jetbrains.kotlin.plugin.compose", version.ref = "kotlin" } -kotlin-android = { id = "org.jetbrains.kotlin.android", version.ref = "kotlin" } +dokka = { id = "org.jetbrains.dokka-javadoc", version = "2.2.0" } nexus-publish = { id = "io.github.gradle-nexus.publish-plugin", version.ref = "nexusPublish" } maven-publish = { id = "maven-publish" } signing = { id = "signing" } diff --git a/gradle/release/libraryInfo.gradle b/gradle/release/libraryInfo.gradle deleted file mode 100644 index 4a5ce04..0000000 --- a/gradle/release/libraryInfo.gradle +++ /dev/null @@ -1,43 +0,0 @@ -class LibraryInfo { - String artifactId - String groupId - - Integer versionMajor - Integer versionMinor - Integer versionPatch - String versionName -} - -def readLibraryProps() { - def versionProps = new Properties() - def file = new File("$projectDir/libraryInfo.properties") - versionProps.load(file.newInputStream()) - - return versionProps -} - -def getLibraryInfo() { - def props = readLibraryProps() - LibraryInfo info = new LibraryInfo() - - info.artifactId = props.get('ARTIFACT_ID') as String - info.groupId = props.get('GROUP_ID') as String - - info.versionMajor = props.get('VERSION_MAJOR') as Integer - info.versionMinor = props.get('VERSION_MINOR') as Integer - info.versionPatch = props.get('VERSION_PATCH') as Integer - def versionPreRelease = props.get('VERSION_PRE_RELEASE') as String - - def versionName = "${info.versionMajor}.${info.versionMinor}.${info.versionPatch}" - if (versionPreRelease != null && !versionPreRelease.isBlank()) { - info.versionName = "${versionName}-${versionPreRelease}" - } else { - info.versionName = versionName - } - - return info -} - -ext { - getLibraryInfo = this.&getLibraryInfo -} \ No newline at end of file diff --git a/gradle/release/publish.gradle b/gradle/release/publish.gradle deleted file mode 100644 index 6b87a78..0000000 --- a/gradle/release/publish.gradle +++ /dev/null @@ -1,123 +0,0 @@ - -tasks.register('androidJavaDoc', Javadoc) { - source = android.sourceSets.main.java.srcDirs - classpath += project.files(android.getBootClasspath().join(File.pathSeparator)) - options.encoding "UTF-8" - options.charSet 'UTF-8' - options.author true - options.version true - failOnError false -} - -tasks.register('androidJavaDocJar', Jar) { - dependsOn androidJavaDoc - archiveClassifier.set('javadoc') - from androidJavaDoc.destinationDir -} - -tasks.register('androidSourcesJar', Jar) { - archiveClassifier.set('sources') - from android.sourceSets.main.java.srcDirs -} - -/** - * Helper to add dependencies to the POM node. This is needed during manual construction - * of the dependencies block - */ -@SuppressWarnings('UnnecessaryQualifiedReference') -static def addPomDependency(groovy.util.Node dependenciesNode, Dependency dependency, String dependencyScope) { - // Ignore incomplete dependencies - if (dependency.name == null || dependency.name == 'unspecified' || dependency.group == null || dependency.version == null) { - return - } - - def dependencyNode = dependenciesNode.appendNode('dependency') - dependencyNode.appendNode('groupId', dependency.group) - dependencyNode.appendNode('artifactId', dependency.name) - dependencyNode.appendNode('version', dependency.version) - dependencyNode.appendNode('scope', dependencyScope) -} - -/** - * Deploy to Maven Central (Sonatype) - * `$ ./gradlew clean library:assembleRelease androidJavaDocJar androidSourcesJar generatePomFileForNexusPublication publishNexusPublicationToSonatypeRepository closeSonatypeStagingRepository` - * - * For publishing locally you can use: - * `./gradlew clean library:assembleRelease androidJavaDocJar androidSourcesJar generatePomFileForNexusPublication publishToMavenLocal -PskipSigning=true` - * - * ** NOTE: ** - * This expects the following environment variables to be present - * - `SONATYPE_TOKEN_USERNAME` : The username for the user token in Sonatype - * - `SONATYPE_TOKEN_PASSWORD` : The password for the user token in Sonatype - * - `SIGNING_KEY_ID` : The ID for the GPG signing key to sign the library with - * - `SIGNING_KEY` : The GPG key to sign the library with - * - `SIGNING_KEY_PASSWORD` : The password for the `SIGNING_KEY` - */ -publishing { - publications { - nexus(MavenPublication) { - groupId rootProject.ext.libraryInfo.groupId - artifactId rootProject.ext.libraryInfo.artifactId - version rootProject.ext.libraryInfo.versionName - - artifact bundleReleaseAar - artifact androidJavaDocJar - artifact androidSourcesJar - - pom { - name = rootProject.ext.libraryInfo.groupId + ":" + rootProject.ext.libraryInfo.artifactId - description = "Property Delegation for the AndroidX DataStore" - url = "https://github.com/brianwernick/DataStoreDelegates" - licenses { - license { - name = "The Apache License, Version 2.0" - url = "http://www.apache.org/licenses/LICENSE-2.0.txt" - } - } - scm { - connection = 'scm:git:github.com/brianwernick/DataStoreDelegates.git' - developerConnection = 'scm:git:ssh://github.com/brianwernick/DataStoreDelegates.git' - url = 'https://github.com/brianwernick/DataStoreDelegates/tree/main' - } - developers { - developer { - name = 'Brian Wernick' - email = 'brian@devbrackets.com' - organization = 'DevBrackets' - organizationUrl = 'https://devbrackets.com' - } - } - - // The generated POM doesn't include dependencies when building Android artifacts, so we manually - // add the dependencies to the POM here - withXml { - def dependenciesNode = asNode().appendNode('dependencies') - - // Iterate over the implementation dependencies, adding a node for each - configurations.implementation.dependencies.each { - addPomDependency(dependenciesNode, it, "runtime") - } - - // Iterate over the api dependencies, adding a node for each - configurations.api.dependencies.each { - addPomDependency(dependenciesNode, it, "compile") - } - } - } - } - } -} - -signing { - useInMemoryPgpKeys( - System.getenv("SIGNING_KEY_ID"), - System.getenv("SIGNING_KEY"), - System.getenv("SIGNING_KEY_PASSWORD"), - ) - - required { - !(findProperty("skipSigning")?.toBoolean() ?: false) - } - - sign publishing.publications.nexus -} diff --git a/gradle/util/testOutput.gradle b/gradle/util/testOutput.gradle deleted file mode 100644 index f7615d4..0000000 --- a/gradle/util/testOutput.gradle +++ /dev/null @@ -1,80 +0,0 @@ -import org.gradle.internal.logging.text.StyledTextOutputFactory -import static org.gradle.internal.logging.text.StyledTextOutput.Style - -/** - * Handles watching the test output for each gradle module, storing the results until the - * test suite has completed, then prints out the results in a condensed manner. - * - * To include this functionality in the project, you just need to apply this script in - * the root `build.gradle` file. e.g. `apply from: './gradle/testOutput.gradle'` - */ - -ext { - moduleTestResults = [] -} - -allprojects { - // Collects test results which are then printed in buildFinished below - tasks.withType(Test).configureEach { - maxParallelForks = Runtime.runtime.availableProcessors().intdiv(2) ?: 1 - - testLogging { - outputs.upToDateWhen { false } - events "failed", "skipped", "standardOut" - exceptionFormat "full" - - afterSuite { desc, result -> - if (!desc.parent) { - moduleTestResults.add([name: project.name, result: result]) - } - } - } - } -} - -gradle.buildFinished { - def testResults = ext.moduleTestResults - def totals = [success: 0, failed: 0, skipped: 0, total: 0] - - testResults.forEach { result -> - totals.success += result.result.successfulTestCount - totals.failed += result.result.failedTestCount - totals.skipped += result.result.skippedTestCount - totals.total += result.result.testCount - - printTestResults( - result.name, - result.result.successfulTestCount, - result.result.failedTestCount, - result.result.skippedTestCount, - result.result.testCount - ) - } - - if (!testResults.isEmpty()) { - printTestResults( - "Project Total", - totals.success, - totals.failed, - totals.skipped, - totals.total - ) - } -} - -private printTestResults(title, passed, failed, skipped, total) { - def style = Style.Success - if (failed > 0) { - style = Style.Failure - } else if (skipped > 0) { - style = Style.Info - } - - def summary = " ${passed} / ${total} passed, ${failed} failed, ${skipped} skipped " - def summaryTitle = " ${title.capitalize()} " - def styledOut = services.get(StyledTextOutputFactory).create("styledTests-out") - - styledOut.withStyle(style).println('╔═' + summaryTitle + '═' * (summary.length() - summaryTitle.length() - 1) + '╗') - styledOut.withStyle(style).println('║' + summary + '║') - styledOut.withStyle(style).println('╚' + '═' * summary.length() + '╝') -} diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 5b59ea8..cf71939 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-9.4.1-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-9.5.1-bin.zip networkTimeout=10000 zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/library/build.gradle b/library/build.gradle deleted file mode 100644 index 5b9dd85..0000000 --- a/library/build.gradle +++ /dev/null @@ -1,58 +0,0 @@ -plugins { - alias libs.plugins.android.library - alias libs.plugins.kotlin.android - alias libs.plugins.maven.publish - alias libs.plugins.signing -} - -afterEvaluate { - apply from: '../gradle/release/publish.gradle' -} - -dependencies { - api libs.kotlin.stdlib.jdk7 - api libs.datastore.preferences - - testImplementation libs.junit - testImplementation libs.robolectric -} - -android { - compileSdk = 37 - - namespace 'com.devbrackets.android.datastore' - - defaultConfig { - minSdkVersion 23 - } - - sourceSets { - main.java.srcDirs += "src/main/kotlin" - test.java.srcDirs += "src/test/kotlin" - } - - buildFeatures { - buildConfig true - } - - compileOptions { - sourceCompatibility JavaVersion.VERSION_11 - targetCompatibility JavaVersion.VERSION_11 - } - - kotlinOptions { - jvmTarget = JavaVersion.VERSION_11 - } - - testOptions { - unitTests { - includeAndroidResources = true - } - targetSdk 37 - } - - lint { - abortOnError false - targetSdk 37 - } -} diff --git a/library/build.gradle.kts b/library/build.gradle.kts new file mode 100644 index 0000000..fcc7884 --- /dev/null +++ b/library/build.gradle.kts @@ -0,0 +1,114 @@ +import release.PublicationManager +import util.ProjectConfig + +plugins { + alias(libs.plugins.android.library) + alias(libs.plugins.dokka) + alias(libs.plugins.maven.publish) + alias(libs.plugins.signing) +} + +dependencies { + api(libs.kotlin.stdlib) + api(libs.datastore.preferences) + + testImplementation(libs.junit) + testImplementation(libs.robolectric) +} + +android { + namespace = "com.devbrackets.android.datastore" + + compileSdk = ProjectConfig.compileSdk + defaultConfig { + minSdk = ProjectConfig.minSdk + } + + + sourceSets { + getByName("main") { + kotlin.directories.add("src/main/kotlin") + } + + getByName("test") { + kotlin.directories.add("src/test/kotlin") + } + } + + buildFeatures { + buildConfig = true + } + + testOptions { + unitTests { + isIncludeAndroidResources = true + } + } + + compileOptions { + sourceCompatibility = JavaVersion.VERSION_11 + targetCompatibility = JavaVersion.VERSION_11 + } + + lint { + abortOnError = false + } +} + +tasks.register("androidJavaDocJar") { + description = "Builds the Javadoc Jar needed for publication" + archiveClassifier.set("javadoc") + + from(tasks.dokkaGenerate) +} + +tasks.register("androidSourcesJar") { + description = "Builds the Sources Jar needed for publication" + archiveClassifier.set("sources") + + android.sourceSets { + from(getByName("main").kotlin.directories) + } +} + +/** + * Deploy to Maven Central (Sonatype) + * `$ ./gradlew clean library:assembleRelease androidJavaDocJar androidSourcesJar generatePomFileForNexusPublication publishNexusPublicationToSonatypeRepository closeSonatypeStagingRepository` + * + * Publish locally (~/.m2): + * `$ ./gradlew clean library:assembleRelease androidJavaDocJar androidSourcesJar generatePomFileForNexusPublication publishToMavenLocal -PskipSigning=true` + * + * ** NOTE: ** + * This expects the following environment variables to be present + * - `SONATYPE_TOKEN_USERNAME` : The username for the user token in Sonatype + * - `SONATYPE_TOKEN_PASSWORD` : The password for the user token in Sonatype + * - `SIGNING_KEY_ID` : The ID for the GPG signing key to sign the library with + * - `SIGNING_KEY` : The GPG key to sign the library with + * - `SIGNING_KEY_PASSWORD` : The password for the `SIGNING_KEY` + */ +afterEvaluate { + publishing { + publications { + PublicationManager.configure( + project, + create("nexus"), + tasks.getByName("bundleReleaseAar"), + tasks.getByName("androidJavaDocJar"), + tasks.getByName("androidSourcesJar") + ) + } + } + + signing { + useInMemoryPgpKeys( + System.getenv("SIGNING_KEY_ID"), + System.getenv("SIGNING_KEY"), + System.getenv("SIGNING_KEY_PASSWORD"), + ) + + val skipSigning = findProperty("skipSigning")?.toString()?.toBoolean() ?: false + isRequired = !skipSigning + + sign(publishing.publications.getByName("nexus")) + } +} \ No newline at end of file diff --git a/settings.gradle b/settings.gradle deleted file mode 100644 index 1be6814..0000000 --- a/settings.gradle +++ /dev/null @@ -1,9 +0,0 @@ -pluginManagement { - repositories { - google() - mavenCentral() - gradlePluginPortal() - } -} - -include ':library', ':demo' \ No newline at end of file diff --git a/settings.gradle.kts b/settings.gradle.kts new file mode 100644 index 0000000..eb3fe9c --- /dev/null +++ b/settings.gradle.kts @@ -0,0 +1,18 @@ +pluginManagement { + repositories { + google { + content { + includeGroupByRegex("com\\.android.*") + includeGroupByRegex("com\\.google.*") + includeGroupByRegex("androidx.*") + } + } + + mavenCentral() + gradlePluginPortal() + } +} + + +include(":library") +include(":demo") \ No newline at end of file