diff --git a/.gitignore b/.gitignore index 13a066e..2a8f5da 100644 --- a/.gitignore +++ b/.gitignore @@ -1,85 +1,72 @@ -!.vscode/extensions.json -!.vscode/launch.json -!.vscode/settings.json -!.vscode/tasks.json -*.class -*.code-workspace -*.ctxt -*.iws -*.log -*.nar -*.rar -*.sublime-* -*.tar.gz -*.zip -.DS_Store -.classpath +### Gradle ### .gradle -.history -.kobalt -.mtj.tmp/ -.mvn/timing.properties -.mvn/wrapper/maven-wrapper.jar -.nb-gradle -.project -.scannerwork -.settings -.vscode/* -/**/.idea/$CACHE_FILE$ -/**/.idea/$PRODUCT_WORKSPACE_FILE$ -/**/.idea/**/caches/build_file_checksums.ser -/**/.idea/**/contentModel.xml -/**/.idea/**/dataSources.ids -/**/.idea/**/dataSources.local.xml -/**/.idea/**/dataSources/ -/**/.idea/**/dbnavigator.xml -/**/.idea/**/dictionaries -/**/.idea/**/dynamic.xml -/**/.idea/**/gradle.xml -/**/.idea/**/httpRequests -/**/.idea/**/libraries -/**/.idea/**/mongoSettings.xml -/**/.idea/**/replstate.xml -/**/.idea/**/shelf -/**/.idea/**/shelf/ -/**/.idea/**/sqlDataSources.xml -/**/.idea/**/tasks.xml -/**/.idea/**/uiDesigner.xml -/**/.idea/**/usage.statistics.xml -/**/.idea/**/workspace.xml -/**/.idea/sonarlint* -/**/.idea_modules/ -Thumbs.db -__pycache__ -atlassian-ide-plugin.xml -bin/ build/ -cmake-build-*/ -com_crashlytics_export_strings.xml -crashlytics-build.properties -crashlytics.properties -dependency-reduced-pom.xml deploy/ -dist/ -ehthumbs.db -fabric.properties -gen/ -gradle.properties + +### Kotlin/JVM ### +*.class +*.log + hs_err_pid* -kobaltBuild -kobaltw*-test -lib/kotlin* -libs/ -local.properties -out/ -pom.xml.asc -pom.xml.next -pom.xml.releaseBackup -pom.xml.tag -pom.xml.versionsBackup -proguard-project.txt -project.properties -release.properties -target/ -test-output -venv +replay_pid* +*.hprof + +*.jar +*.war +*.nar +*.ear +*.zip +*.tar.gz +*.rar + + +### IntelliJ ### +.idea/**/* + +### Eclipse ### +.metadata +bin/ +tmp/ +*.tmp +*.bak +*.swp +*~.nib +.settings/ +.loadpath +.recommenders +.classpath + +.apt_generated/ +.apt_generated_test/ +.project + + +### Linux ### +*~ +.fuse_hidden* +.Trash-* +.nfs* + + +### Windows ### +[Dd]esktop.ini +$RECYCLE.BIN/ +*.lnk + + +### macOS ### +.DS_Store +._* + +# Icon must end with two \r +Icon + + +########################### + +# place overrides last, so they're not themselves overridden + +!gradle/wrapper/gradle-wrapper.jar +!gradle/wrapper/gradle-wrapper.properties + +!.idea/copyright/** diff --git a/.idea/.gitignore b/.idea/.gitignore deleted file mode 100644 index 26d3352..0000000 --- a/.idea/.gitignore +++ /dev/null @@ -1,3 +0,0 @@ -# Default ignored files -/shelf/ -/workspace.xml diff --git a/.idea/compiler.xml b/.idea/compiler.xml deleted file mode 100644 index fb7f4a8..0000000 --- a/.idea/compiler.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/.idea/inspectionProfiles/Project_Default.xml b/.idea/inspectionProfiles/Project_Default.xml deleted file mode 100644 index 1e01b48..0000000 --- a/.idea/inspectionProfiles/Project_Default.xml +++ /dev/null @@ -1,8 +0,0 @@ - - - - \ No newline at end of file diff --git a/.idea/jarRepositories.xml b/.idea/jarRepositories.xml deleted file mode 100644 index cfd3ca8..0000000 --- a/.idea/jarRepositories.xml +++ /dev/null @@ -1,25 +0,0 @@ - - - - - - - - - - - - - \ No newline at end of file diff --git a/.idea/kotlinc.xml b/.idea/kotlinc.xml deleted file mode 100644 index 2b8a50f..0000000 --- a/.idea/kotlinc.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml deleted file mode 100644 index 2540c68..0000000 --- a/.idea/misc.xml +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - - \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml deleted file mode 100644 index 35eb1dd..0000000 --- a/.idea/vcs.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/build.gradle.kts b/build.gradle.kts new file mode 100644 index 0000000..3dd9d03 --- /dev/null +++ b/build.gradle.kts @@ -0,0 +1,23 @@ +/* + * Copyright 2001-2023 Geert Bevin (gbevin[remove] at uwyn dot com) + * Copyright 2022-2023 Erik C. Thauvin (erik@thauvin.net) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +plugins { + buildsrc.conventions.base +} + +group = "net.thauvin.erik" +version = "1.3.1-SNAPSHOT" diff --git a/buildSrc/build.gradle.kts b/buildSrc/build.gradle.kts new file mode 100644 index 0000000..788b119 --- /dev/null +++ b/buildSrc/build.gradle.kts @@ -0,0 +1,12 @@ +plugins { + `kotlin-dsl` +} + +dependencies { + implementation("com.github.ben-manes:gradle-versions-plugin:0.44.0") + implementation("io.gitlab.arturbosch.detekt:detekt-gradle-plugin:1.22.0") + implementation("org.jetbrains.dokka:dokka-gradle-plugin:1.7.20") + implementation("org.jetbrains.kotlin:kotlin-gradle-plugin:1.8.0") + implementation("org.jetbrains.kotlinx:kover-gradle-plugin:0.7.0") + implementation("org.sonarsource.scanner.gradle:sonarqube-gradle-plugin:3.5.0.2730") +} diff --git a/buildSrc/settings.gradle.kts b/buildSrc/settings.gradle.kts new file mode 100644 index 0000000..bf6ac65 --- /dev/null +++ b/buildSrc/settings.gradle.kts @@ -0,0 +1,16 @@ +rootProject.name = "buildSrc" + +pluginManagement { + repositories { + mavenCentral() + gradlePluginPortal() + } +} + +@Suppress("UnstableApiUsage") +dependencyResolutionManagement { + repositories { + mavenCentral() + gradlePluginPortal() + } +} diff --git a/buildSrc/src/main/kotlin/buildsrc/conventions/base.gradle.kts b/buildSrc/src/main/kotlin/buildsrc/conventions/base.gradle.kts new file mode 100644 index 0000000..59e3a56 --- /dev/null +++ b/buildSrc/src/main/kotlin/buildsrc/conventions/base.gradle.kts @@ -0,0 +1,18 @@ +package buildsrc.conventions + +/** common config for all subprojects */ + +plugins { + base +} + +if (project != rootProject) { + project.version = rootProject.version + project.group = rootProject.group +} + +tasks.withType().configureEach { + // https://docs.gradle.org/current/userguide/working_with_files.html#sec:reproducible_archives + isPreserveFileTimestamps = false + isReproducibleFileOrder = true +} diff --git a/buildSrc/src/main/kotlin/buildsrc/conventions/code-quality.gradle.kts b/buildSrc/src/main/kotlin/buildsrc/conventions/code-quality.gradle.kts new file mode 100644 index 0000000..f9c3d13 --- /dev/null +++ b/buildSrc/src/main/kotlin/buildsrc/conventions/code-quality.gradle.kts @@ -0,0 +1,53 @@ +/* + * Copyright 2001-2023 Geert Bevin (gbevin[remove] at uwyn dot com) + * Copyright 2022-2023 Erik C. Thauvin (erik@thauvin.net) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package buildsrc.conventions + +import buildsrc.utils.Rife2TestListener +import org.gradle.api.tasks.testing.logging.TestExceptionFormat +import org.gradle.api.tasks.testing.logging.TestLogEvent +import org.sonarqube.gradle.SonarTask + +plugins { + id("org.sonarqube") + id("io.gitlab.arturbosch.detekt") + id("org.jetbrains.kotlinx.kover") +} + +sonarqube { + properties { + property("sonar.projectName", rootProject.name) + property("sonar.projectKey", "ethauvin_${rootProject.name}") + property("sonar.organization", "ethauvin-github") + property("sonar.host.url", "https://sonarcloud.io") + property("sonar.sourceEncoding", "UTF-8") + property("sonar.coverage.jacoco.xmlReportPaths", "${project.buildDir}/reports/kover/report.xml") + } +} + +tasks.withType().configureEach { + dependsOn(tasks.matching { it.name == "koverXmlReport" }) +} + +tasks.withType().configureEach { + val testsBadgeApiKey = providers.gradleProperty("testsBadgeApiKey") + addTestListener(Rife2TestListener(testsBadgeApiKey)) + testLogging { + exceptionFormat = TestExceptionFormat.FULL + events = setOf(TestLogEvent.PASSED, TestLogEvent.SKIPPED, TestLogEvent.FAILED) + } +} diff --git a/buildSrc/src/main/kotlin/buildsrc/conventions/lang/kotlin-jvm.gradle.kts b/buildSrc/src/main/kotlin/buildsrc/conventions/lang/kotlin-jvm.gradle.kts new file mode 100644 index 0000000..790e694 --- /dev/null +++ b/buildSrc/src/main/kotlin/buildsrc/conventions/lang/kotlin-jvm.gradle.kts @@ -0,0 +1,42 @@ +package buildsrc.conventions.lang + +import buildsrc.utils.Rife2TestListener +import org.gradle.api.JavaVersion +import org.gradle.api.tasks.testing.Test +import org.gradle.api.tasks.testing.logging.TestExceptionFormat +import org.gradle.api.tasks.testing.logging.TestLogEvent +import org.gradle.kotlin.dsl.withType +import org.jetbrains.kotlin.gradle.dsl.JvmTarget +import org.jetbrains.kotlin.gradle.targets.jvm.KotlinJvmTarget +import org.jetbrains.kotlin.gradle.tasks.KotlinCompile +import org.sonarqube.gradle.SonarTask + +/** + * Common configuration for Kotlin/JVM projects + * + * (this can be removed after Kotlin Multiplatform migration) + */ + +plugins { + id("buildsrc.conventions.base") + kotlin("jvm") + id("buildsrc.conventions.code-quality") +} + +java { + withSourcesJar() +} + +kotlin { + jvmToolchain(11) +} + +tasks.withType().configureEach { + compilerOptions { + jvmTarget.set(JvmTarget.JVM_11) + } +} + +tasks.withType().configureEach { + useJUnitPlatform() +} diff --git a/buildSrc/src/main/kotlin/buildsrc/conventions/lang/kotlin-multiplatform-base.gradle.kts b/buildSrc/src/main/kotlin/buildsrc/conventions/lang/kotlin-multiplatform-base.gradle.kts new file mode 100644 index 0000000..4af978b --- /dev/null +++ b/buildSrc/src/main/kotlin/buildsrc/conventions/lang/kotlin-multiplatform-base.gradle.kts @@ -0,0 +1,45 @@ +package buildsrc.conventions.lang + +import org.jetbrains.kotlin.gradle.targets.jvm.KotlinJvmTarget + + +/** + * Base configuration for all Kotlin/Multiplatform conventions. + * + * This plugin does not enable any Kotlin target. To enable a target in a subproject, prefer applying specific Kotlin + * target convention plugins. + */ + +plugins { + id("buildsrc.conventions.base") + kotlin("multiplatform") +} + + +kotlin { + jvmToolchain(11) + + targets.configureEach { + compilations.configureEach { + kotlinOptions { + // nothin' yet + } + } + } + + // configure all Kotlin/JVM Tests to use JUnit + targets.withType().configureEach { + testRuns.configureEach { + executionTask.configure { + useJUnitPlatform() + } + } + } + + sourceSets.configureEach { + languageSettings { +// languageVersion = +// apiVersion = + } + } +} diff --git a/buildSrc/src/main/kotlin/buildsrc/conventions/lang/kotlin-multiplatform-js.gradle.kts b/buildSrc/src/main/kotlin/buildsrc/conventions/lang/kotlin-multiplatform-js.gradle.kts new file mode 100644 index 0000000..2a0034a --- /dev/null +++ b/buildSrc/src/main/kotlin/buildsrc/conventions/lang/kotlin-multiplatform-js.gradle.kts @@ -0,0 +1,18 @@ +package buildsrc.conventions.lang + +/** conventions for a Kotlin/JS subproject */ + +plugins { + id("buildsrc.conventions.lang.kotlin-multiplatform-base") +} + +kotlin { + targets { + js(IR) { + browser() + nodejs() + } + } +} + +relocateKotlinJsStore() diff --git a/buildSrc/src/main/kotlin/buildsrc/conventions/lang/kotlin-multiplatform-jvm.gradle.kts b/buildSrc/src/main/kotlin/buildsrc/conventions/lang/kotlin-multiplatform-jvm.gradle.kts new file mode 100644 index 0000000..6bbef24 --- /dev/null +++ b/buildSrc/src/main/kotlin/buildsrc/conventions/lang/kotlin-multiplatform-jvm.gradle.kts @@ -0,0 +1,11 @@ +package buildsrc.conventions.lang + +plugins { + id("buildsrc.conventions.lang.kotlin-multiplatform-base") +} + +kotlin { + jvm { + withJava() + } +} diff --git a/buildSrc/src/main/kotlin/buildsrc/conventions/lang/kotlin-multiplatform-native.gradle.kts b/buildSrc/src/main/kotlin/buildsrc/conventions/lang/kotlin-multiplatform-native.gradle.kts new file mode 100644 index 0000000..7e8bb2a --- /dev/null +++ b/buildSrc/src/main/kotlin/buildsrc/conventions/lang/kotlin-multiplatform-native.gradle.kts @@ -0,0 +1,102 @@ +package buildsrc.conventions.lang + +/** conventions for a Kotlin/Native subproject */ + +plugins { + id("buildsrc.conventions.lang.kotlin-multiplatform-base") +} + +kotlin { + + // Native targets all extend commonMain and commonTest. + // + // Some targets (ios, tvos, watchos) are shortcuts provided by the Kotlin DSL, that + // provide additional targets, except for 'simulators' which must be defined manually. + // https://kotlinlang.org/docs/multiplatform-share-on-platforms.html#use-target-shortcuts + // + // common/ + // └── native/ + // ├── linuxX64 + // ├── mingwX64 + // ├── macosX64 + // ├── macosArm64 + // ├── ios/ (shortcut) + // │ ├── iosArm64 + // │ ├── iosX64 + // │ └── iosSimulatorArm64 + // ├── tvos/ (shortcut) + // │ ├── tvosArm64 + // │ ├── tvosX64 + // │ └── tvosSimulatorArm64Main + // └── watchos/ (shortcut) + // ├── watchosArm32 + // ├── watchosArm64 + // ├── watchosX64 + // └── watchosSimulatorArm64Main + + targets { + linuxX64() + + mingwX64() + + macosX64() + macosArm64() + + // https://kotlinlang.org/docs/multiplatform-share-on-platforms.html#use-target-shortcuts + ios() // iosArm64, iosX64 + watchos() // watchosArm32, watchosArm64, watchosX64 + tvos() // tvosArm64, tvosX64 + + iosSimulatorArm64() + tvosSimulatorArm64() + watchosSimulatorArm64() + } + + @Suppress("UNUSED_VARIABLE") + sourceSets { + val commonMain by getting {} + val commonTest by getting {} + + val nativeMain by creating { dependsOn(commonMain) } + val nativeTest by creating { dependsOn(commonTest) } + + // Linux + val linuxX64Main by getting { dependsOn(nativeMain) } + val linuxX64Test by getting { dependsOn(nativeTest) } + + // Windows - MinGW + val mingwX64Main by getting { dependsOn(nativeMain) } + val mingwX64Test by getting { dependsOn(nativeTest) } + + // Apple - macOS + val macosArm64Main by getting { dependsOn(nativeMain) } + val macosArm64Test by getting { dependsOn(nativeTest) } + + val macosX64Main by getting { dependsOn(nativeMain) } + val macosX64Test by getting { dependsOn(nativeTest) } + + // Apple - iOS + val iosMain by getting { dependsOn(nativeMain) } + val iosTest by getting { dependsOn(nativeTest) } + +// val iosSimulatorArm64Main by getting { dependsOn(iosMain) } +// val iosSimulatorArm64Test by getting { dependsOn(iosTest) } + +// // Apple - tvOS +// val tvosMain by getting { dependsOn(nativeMain) } +// val tvosTest by getting { dependsOn(nativeTest) } +// +// val tvosSimulatorArm64Main by getting { dependsOn(tvosMain) } +// val tvosSimulatorArm64Test by getting { dependsOn(tvosTest) } +// +// // Apple - watchOS +// val watchosMain by getting { dependsOn(nativeMain) } +// val watchosTest by getting { dependsOn(nativeTest) } +// +// val watchosSimulatorArm64Main by getting { dependsOn(watchosMain) } +// val watchosSimulatorArm64Test by getting { dependsOn(watchosTest) } + + // val iosArm32Main by getting { dependsOn(desktopMain) } + // val iosArm32Test by getting { dependsOn(nativeTest) } + } +} diff --git a/buildSrc/src/main/kotlin/buildsrc/conventions/lang/kotlinJsExtensions.kt b/buildSrc/src/main/kotlin/buildsrc/conventions/lang/kotlinJsExtensions.kt new file mode 100644 index 0000000..eefdc94 --- /dev/null +++ b/buildSrc/src/main/kotlin/buildsrc/conventions/lang/kotlinJsExtensions.kt @@ -0,0 +1,18 @@ +package buildsrc.conventions.lang + +import org.gradle.api.Project +import org.gradle.kotlin.dsl.configure +import org.jetbrains.kotlin.gradle.targets.js.yarn.YarnRootExtension + +/** + * `kotlin-js` and `kotlin-multiplatform` plugins adds a directory in the root-dir for the Yarn + * lockfile. That's a bit annoying. It's a little neater if it's in the Gradle dir, next to the + * version catalog. + */ +internal fun Project.relocateKotlinJsStore() { + afterEvaluate { + rootProject.extensions.configure { + lockFileDirectory = project.rootDir.resolve("gradle/kotlin-js-store") + } + } +} diff --git a/buildSrc/src/main/kotlin/buildsrc/conventions/publishing.gradle.kts b/buildSrc/src/main/kotlin/buildsrc/conventions/publishing.gradle.kts new file mode 100644 index 0000000..2390479 --- /dev/null +++ b/buildSrc/src/main/kotlin/buildsrc/conventions/publishing.gradle.kts @@ -0,0 +1,105 @@ +/* + * Copyright 2001-2023 Geert Bevin (gbevin[remove] at uwyn dot com) + * Copyright 2022-2023 Erik C. Thauvin (erik@thauvin.net) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package buildsrc.conventions + +plugins { + id("maven-publish") + id("signing") + id("org.jetbrains.dokka") +} + +val gitHub = "ethauvin/${rootProject.name}" +val mavenUrl = "https://github.com/$gitHub" +val isSnapshotVersion = { project.version.toString().contains("SNAPSHOT") } + +publishing { + publications { + withType().configureEach { + pom { + name.set("UrlEncoder for Kotlin") + description.set(project.description) + url.set(mavenUrl) + licenses { + license { + name.set("The Apache License, Version 2.0") + url.set("http://www.apache.org/licenses/LICENSE-2.0.txt") + } + } + developers { + developer { + id.set("gbevin") + name.set("Geert Bevin") + email.set("gbevin@uwyn.com") + url.set("https://github.com/gbevin") + } + developer { + id.set("ethauvin") + name.set("Erik C. Thauvin") + email.set("erik@thauvin.net") + url.set("https://erik.thauvin.net/") + } + } + scm { + connection.set("scm:git://github.com/$gitHub.git") + developerConnection.set("scm:git@github.com:$gitHub.git") + url.set(mavenUrl) + } + issueManagement { + system.set("GitHub") + url.set("$mavenUrl/issues") + } + } + } + } + repositories { + maven( + if (isSnapshotVersion()) { + uri("https://oss.sonatype.org/content/repositories/snapshots/") + } else { + uri("https://oss.sonatype.org/service/local/staging/deploy/maven2/") + } + ) { + name = "ossrh" + credentials(PasswordCredentials::class) + } + } +} + +signing { + useGpgCmd() + sign(publishing.publications) + + setRequired({ + !isSnapshotVersion() || gradle.taskGraph.hasTask("publish") + }) +} +tasks.withType().configureEach { + val signingRequiredPredicate = provider { signing.isRequired } + onlyIf { signingRequiredPredicate.get() } +} + +// https://youtrack.jetbrains.com/issue/KT-46466 +val signingTasks = tasks.withType() +tasks.withType().configureEach { + dependsOn(signingTasks) +} + +val javadocJar by tasks.registering(Jar::class) { + dependsOn(tasks.dokkaJavadoc) + from(tasks.dokkaJavadoc) + archiveClassifier.set("javadoc") +} diff --git a/buildSrc/src/main/kotlin/buildsrc/utils/Rife2TestListener.kt b/buildSrc/src/main/kotlin/buildsrc/utils/Rife2TestListener.kt new file mode 100644 index 0000000..748b064 --- /dev/null +++ b/buildSrc/src/main/kotlin/buildsrc/utils/Rife2TestListener.kt @@ -0,0 +1,65 @@ +/* + * Copyright 2001-2023 Geert Bevin (gbevin[remove] at uwyn dot com) + * Copyright 2022-2023 Erik C. Thauvin (erik@thauvin.net) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package buildsrc.utils + +import org.gradle.api.provider.Provider +import org.gradle.api.tasks.testing.TestDescriptor +import org.gradle.api.tasks.testing.TestListener +import org.gradle.api.tasks.testing.TestResult +import java.net.URI +import java.net.http.HttpClient +import java.net.http.HttpRequest +import java.net.http.HttpResponse + +class Rife2TestListener( + private val testBadgeApiKey: Provider +) : TestListener { + override fun beforeTest(p0: TestDescriptor?) = Unit + override fun beforeSuite(p0: TestDescriptor?) = Unit + override fun afterTest(desc: TestDescriptor, result: TestResult) = Unit + override fun afterSuite(desc: TestDescriptor, result: TestResult) { + if (desc.parent == null) { + val passed = result.successfulTestCount + val failed = result.failedTestCount + val skipped = result.skippedTestCount + + val apiKey = testBadgeApiKey.orNull + + if (apiKey != null) { + println(apiKey) + val response: HttpResponse = HttpClient.newHttpClient() + .send( + HttpRequest.newBuilder() + .uri( + URI( + "https://rife2.com/tests-badge/update/net.thauvin.erik/urlencoder?" + + "apiKey=$apiKey&" + + "passed=$passed&" + + "failed=$failed&" + + "skipped=$skipped" + ) + ) + .POST(HttpRequest.BodyPublishers.noBody()) + .build(), HttpResponse.BodyHandlers.ofString() + ) + println("RESPONSE: ${response.statusCode()}") + println(response.body()) + } + } + } +} diff --git a/lib/build.gradle.kts b/lib/build.gradle.kts index 5b12abf..eb0edae 100644 --- a/lib/build.gradle.kts +++ b/lib/build.gradle.kts @@ -1,42 +1,17 @@ -import org.gradle.api.tasks.testing.logging.TestExceptionFormat -import org.gradle.api.tasks.testing.logging.TestLogEvent import org.jetbrains.dokka.gradle.DokkaTask -import org.jetbrains.kotlin.gradle.tasks.KotlinCompile -import java.net.URI -import java.net.http.HttpClient -import java.net.http.HttpRequest -import java.net.http.HttpResponse plugins { + buildsrc.conventions.lang.`kotlin-jvm` + buildsrc.conventions.publishing id("application") - id("com.github.ben-manes.versions") version "0.44.0" - id("io.gitlab.arturbosch.detekt") version "1.22.0" - id("java-library") - id("maven-publish") - id("org.jetbrains.dokka") version "1.7.20" - id("org.jetbrains.kotlin.jvm") version "1.8.0" - id("org.jetbrains.kotlinx.kover") version "0.6.1" - id("org.sonarqube") version "3.5.0.2730" - id("signing") + id("com.github.ben-manes.versions") } description = "A simple defensive library to encode/decode URL components" -group = "net.thauvin.erik" -version = "1.3.1-SNAPSHOT" - -val mavenName = "UrlEncoder" -val deployDir = "deploy" -val gitHub = "ethauvin/${rootProject.name}" -val mavenUrl = "https://github.com/$gitHub" -val publicationName = "mavenJava" -val myClassName = "$group.${rootProject.name}.$mavenName" - -repositories { - mavenCentral() - maven { url = uri("https://oss.sonatype.org/content/repositories/snapshots") } -} +val deployDir = project.layout.projectDirectory.dir("deploy") +val urlEncoderMainClass = "net.thauvin.erik.urlencoder.UrlEncoder" dependencies { // testImplementation("com.willowtreeapps.assertk:assertk-jvm:0.25") @@ -47,42 +22,19 @@ base { archivesName.set(rootProject.name) } -java { - sourceCompatibility = JavaVersion.VERSION_11 - targetCompatibility = JavaVersion.VERSION_11 - withSourcesJar() -} - application { - mainClass.set(myClassName) -} - -sonarqube { - properties { - property("sonar.projectName", rootProject.name) - property("sonar.projectKey", "ethauvin_${rootProject.name}") - property("sonar.organization", "ethauvin-github") - property("sonar.host.url", "https://sonarcloud.io") - property("sonar.sourceEncoding", "UTF-8") - property("sonar.coverage.jacoco.xmlReportPaths", "${project.buildDir}/reports/kover/xml/report.xml") - } -} - -val javadocJar by tasks.creating(Jar::class) { - dependsOn(tasks.dokkaJavadoc) - from(tasks.dokkaJavadoc) - archiveClassifier.set("javadoc") + mainClass.set(urlEncoderMainClass) } tasks { jar { manifest { - attributes["Main-Class"] = myClassName + attributes["Main-Class"] = urlEncoderMainClass } } - val fatJar = register("fatJar") { - group = "build" + val fatJar by registering(Jar::class) { + group = LifecycleBasePlugin.BUILD_GROUP dependsOn.addAll(listOf("compileJava", "compileKotlin", "processResources")) archiveClassifier.set("all") duplicatesStrategy = DuplicatesStrategy.EXCLUDE @@ -97,65 +49,10 @@ tasks { dependsOn(fatJar) } - withType().configureEach { - kotlinOptions.jvmTarget = java.targetCompatibility.toString() - } - - test { - useJUnitPlatform() - addTestListener(object : TestListener { - override fun beforeTest(p0: TestDescriptor?) = Unit - override fun beforeSuite(p0: TestDescriptor?) = Unit - override fun afterTest(desc: TestDescriptor, result: TestResult) = Unit - override fun afterSuite(desc: TestDescriptor, result: TestResult) { - if (desc.parent == null) { - val passed = result.successfulTestCount - val failed = result.failedTestCount - val skipped = result.skippedTestCount - - if (project.properties["testsBadgeApiKey"] != null) { - val apiKey = project.properties["testsBadgeApiKey"] - println(apiKey) - val response: HttpResponse = HttpClient.newHttpClient() - .send( - HttpRequest.newBuilder() - .uri( - URI( - "https://rife2.com/tests-badge/update/net.thauvin.erik/urlencoder?" + - "apiKey=$apiKey&" + - "passed=$passed&" + - "failed=$failed&" + - "skipped=$skipped" - ) - ) - .POST(HttpRequest.BodyPublishers.noBody()) - .build(), HttpResponse.BodyHandlers.ofString() - ) - println("RESPONSE: ${response.statusCode()}") - println(response.body()) - } - } - } - }) - } - - withType { - testLogging { - exceptionFormat = TestExceptionFormat.FULL - events = setOf(TestLogEvent.PASSED, TestLogEvent.SKIPPED, TestLogEvent.FAILED) - } - } - - withType { + withType().configureEach { destination = file("$projectDir/pom.xml") } - clean { - doLast { - project.delete(fileTree(deployDir)) - } - } - withType().configureEach { dokkaSourceSets { named("main") { @@ -164,7 +61,9 @@ tasks { } } - val copyToDeploy by registering(Copy::class) { + val copyToDeploy by registering(Sync::class) { + description = "Copies all needed files to the 'deploy' directory." + group = PublishingPlugin.PUBLISH_TASK_GROUP from(configurations.runtimeClasspath) { exclude("annotations-*.jar") } @@ -173,73 +72,22 @@ tasks { } register("deploy") { - description = "Copies all needed files to the $deployDir directory." + description = "Copies all needed files to the 'deploy' directory." group = PublishingPlugin.PUBLISH_TASK_GROUP - dependsOn(clean, build, jar) - outputs.dir(deployDir) - inputs.files(copyToDeploy) - mustRunAfter(clean) + dependsOn(build, copyToDeploy) } - "sonar" { - dependsOn(koverReport) + clean { + delete(deployDir) } } publishing { publications { - create(publicationName) { + create("mavenJava") { from(components["java"]) artifactId = rootProject.name - artifact(javadocJar) - pom { - name.set("$mavenName for Kotlin") - description.set(project.description) - url.set(mavenUrl) - licenses { - license { - name.set("The Apache License, Version 2.0") - url.set("http://www.apache.org/licenses/LICENSE-2.0.txt") - } - } - developers { - developer { - id.set("gbevin") - name.set("Geert Bevin") - email.set("gbevin@uwyn.com") - url.set("https://github.com/gbevin") - } - developer { - id.set("ethauvin") - name.set("Erik C. Thauvin") - email.set("erik@thauvin.net") - url.set("https://erik.thauvin.net/") - } - } - scm { - connection.set("scm:git://github.com/$gitHub.git") - developerConnection.set("scm:git@github.com:$gitHub.git") - url.set(mavenUrl) - } - issueManagement { - system.set("GitHub") - url.set("$mavenUrl/issues") - } - } - } - } - repositories { - maven { - name = "ossrh" - url = if (project.version.toString().contains("SNAPSHOT")) - uri("https://oss.sonatype.org/content/repositories/snapshots/") else - uri("https://oss.sonatype.org/service/local/staging/deploy/maven2/") - credentials(PasswordCredentials::class) + artifact(tasks.javadocJar) } } } - -signing { - useGpgCmd() - sign(publishing.publications[publicationName]) -} diff --git a/settings.gradle.kts b/settings.gradle.kts index 0cb10ee..e75db1d 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -1,12 +1,25 @@ -/* - * This file was generated by the Gradle 'init' task. - * - * The settings file is used to specify which projects to include in your build. - * - * Detailed information about configuring a multi-project build in Gradle can be found - * in the user manual at https://docs.gradle.org/7.6/userguide/multi_project_builds.html - * This project uses @Incubating APIs which are subject to change. - */ - rootProject.name = "urlencoder" -include("lib") + +pluginManagement { + repositories { + mavenCentral() + gradlePluginPortal() + } +} + +@Suppress("UnstableApiUsage") +dependencyResolutionManagement { + repositoriesMode.set(RepositoriesMode.PREFER_SETTINGS) + + repositories { + mavenCentral() + maven("https://oss.sonatype.org/content/repositories/snapshots") { + name = "Sonatype Snapshots" + mavenContent { snapshotsOnly() } + } + } +} + +include( + ":lib", +)