From 5f198b0d900732dd301c4811c6fe69aa556ae877 Mon Sep 17 00:00:00 2001 From: Nik Clayton Date: Mon, 15 Apr 2024 15:06:55 +0200 Subject: [PATCH] build: Simplify build infrastructure for command line tools (#613) Provide a build convention plugin for command line tools, and use `libs.versions.toml` for command line tool dependencies. Adjust the individual tool `build.gradle.kts` files accordingly. Remove unnecessary `gradle.properties` and `settings.gradle` files for projects that are included as subprojects, not included builds. Add a trivial test for each command line tool so there are tests to run and provide some confidence that automated library upgrades don't break command line tool compilation. --- build-logic/convention/build.gradle.kts | 4 ++ .../kotlin/app/pachli/ToolConventionPlugin.kt | 38 +++++++++++++++++++ gradle/libs.versions.toml | 18 +++++++++ settings.gradle.kts | 1 + tools/build.gradle.kts | 12 ++++-- tools/mklanguages/build.gradle.kts | 23 +++-------- .../kotlin/app/pachli/mklanguages/AppTest.kt | 25 ++++++------ .../pachli/mklanguages/ValuesParserTest.kt | 4 +- tools/mkserverversions/build.gradle.kts | 15 +------- .../app/pachli/mkserverversions/AppTest.kt} | 25 ++++++------ tools/mvstring/build.gradle.kts | 18 ++------- tools/mvstring/settings.gradle.kts | 30 --------------- .../kotlin/app/pachli/mvstring/AppTest.kt} | 23 +++++------ 13 files changed, 120 insertions(+), 116 deletions(-) create mode 100644 build-logic/convention/src/main/kotlin/app/pachli/ToolConventionPlugin.kt rename checks/settings.gradle.kts => tools/mklanguages/src/test/kotlin/app/pachli/mklanguages/AppTest.kt (65%) rename tools/{mklanguages/settings.gradle.kts => mkserverversions/src/test/kotlin/app/pachli/mkserverversions/AppTest.kt} (65%) delete mode 100644 tools/mvstring/settings.gradle.kts rename tools/{mkserverversions/settings.gradle.kts => mvstring/src/test/kotlin/app/pachli/mvstring/AppTest.kt} (69%) diff --git a/build-logic/convention/build.gradle.kts b/build-logic/convention/build.gradle.kts index 80e7019b3..28fc2b429 100644 --- a/build-logic/convention/build.gradle.kts +++ b/build-logic/convention/build.gradle.kts @@ -63,5 +63,9 @@ gradlePlugin { id = "pachli.android.lint" implementationClass = "AndroidLintConventionPlugin" } + register("tool") { + id = "pachli.tool" + implementationClass = "ToolConventionPlugin" + } } } diff --git a/build-logic/convention/src/main/kotlin/app/pachli/ToolConventionPlugin.kt b/build-logic/convention/src/main/kotlin/app/pachli/ToolConventionPlugin.kt new file mode 100644 index 000000000..4f8857e19 --- /dev/null +++ b/build-logic/convention/src/main/kotlin/app/pachli/ToolConventionPlugin.kt @@ -0,0 +1,38 @@ +/* + * Copyright 2024 Pachli Association + * + * This file is a part of Pachli. + * + * This program is free software; you can redistribute it and/or modify it under the terms of the + * GNU General Public License as published by the Free Software Foundation; either version 3 of the + * License, or (at your option) any later version. + * + * Pachli is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even + * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General + * Public License for more details. + * + * You should have received a copy of the GNU General Public License along with Pachli; if not, + * see . + */ + +import app.pachli.libs +import org.gradle.api.Plugin +import org.gradle.api.Project +import org.gradle.kotlin.dsl.dependencies + +class ToolConventionPlugin : Plugin { + override fun apply(target: Project) { + with(target) { + dependencies { + add("implementation", libs.findLibrary("kotlin-logging-jvm").get()) + add("implementation", libs.findLibrary("logback").get()) + add("implementation", libs.findLibrary("clikt").get()) + + add("testImplementation", libs.findLibrary("truth").get()) + add("testImplementation", libs.findLibrary("junit-jupiter").get()) + add("testImplementation", libs.findLibrary("junit-jupiter-params").get()) + add("testRuntimeOnly", "org.junit.platform:junit-platform-launcher") + } + } + } +} diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 0aa7084a8..311559ca7 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -73,6 +73,14 @@ turbine = "1.1.0" unified-push = "2.1.1" xmlwriter = "1.0.4" +# Tool dependencies +betterparse = "0.4.4" +clikt = "4.3.0" +icu4j = "74.2" +junit-jupiter = "5.10.2" +kotlin-logging-jvm = "6.0.4" +logback = "1.5.3" + [plugins] aboutlibraries = { id = "com.mikepenz.aboutlibraries.plugin", version.ref = "aboutlibraries" } android-application = { id = "com.android.application", version.ref = "agp" } @@ -94,6 +102,7 @@ pachli-android-application-flavors = { id = "pachli.android.application.flavors" pachli-android-hilt = { id = "pachli.android.hilt", version = "unspecified" } pachli-android-library = { id = "pachli.android.library", version = "unspecified" } pachli-android-room = { id = "pachli.android.room", version = "unspecified" } +pachli-tool = { id = "pachli.tool", version = "unspecified" } [libraries] aboutlibraries-core = { module = "com.mikepenz:aboutlibraries-core", version.ref = "aboutlibraries" } @@ -162,6 +171,8 @@ hilt-android = { module = "com.google.dagger:hilt-android", version.ref = "hilt" hilt-compiler = { module = "com.google.dagger:hilt-compiler", version.ref = "hilt" } hilt-android-testing = { module = "com.google.dagger:hilt-android-testing", version.ref = "hilt" } junit = { module = "junit:junit", version.ref = "junit" } +junit-jupiter = { module = "org.junit.jupiter:junit-jupiter", version.ref = "junit-jupiter" } +junit-jupiter-params = { module = "org.junit.jupiter:junit-jupiter-params", version.ref = "junit-jupiter" } kotlin-result = { module = "com.michael-bull.kotlin-result:kotlin-result", version.ref = "kotlin-result" } kotlin-result-coroutines = { module = "com.michael-bull.kotlin-result:kotlin-result-coroutines", version.ref = "kotlin-result" } kotlinx-coroutines-android = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-android", version.ref = "coroutines" } @@ -200,6 +211,13 @@ turbine = { module = "app.cash.turbine:turbine", version.ref = "turbine" } unified-push = { module = "com.github.UnifiedPush:android-connector", version.ref = "unified-push" } xmlwriter = { module = "org.pageseeder.xmlwriter:pso-xmlwriter", version.ref = "xmlwriter" } +# Tool libraries +betterparse = { module = "com.github.h0tk3y.betterParse:better-parse", version.ref = "betterparse" } +clikt = { module = "com.github.ajalt.clikt:clikt", version.ref = "clikt" } +icu4j = { module = "com.ibm.icu:icu4j", version.ref = "icu4j"} +kotlin-logging-jvm = { module = "io.github.oshai:kotlin-logging-jvm", version.ref = "kotlin-logging-jvm" } +logback = { module = "ch.qos.logback:logback-classic", version.ref = "logback" } + # build-logic dependencies android-gradlePlugin = { module = "com.android.tools.build:gradle", version.ref = "agp" } kotlin-gradlePlugin = { module = "org.jetbrains.kotlin:kotlin-gradle-plugin", version.ref = "kotlin" } diff --git a/settings.gradle.kts b/settings.gradle.kts index 07d5882b4..f8b5bbe92 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -65,6 +65,7 @@ include(":core:ui") include(":feature:about") include(":feature:lists") include(":feature:login") +include(":tools") include(":tools:mklanguages") include(":tools:mkserverversions") include(":tools:mvstring") diff --git a/tools/build.gradle.kts b/tools/build.gradle.kts index e1cab4daf..d8653c68a 100644 --- a/tools/build.gradle.kts +++ b/tools/build.gradle.kts @@ -17,17 +17,21 @@ import org.jetbrains.kotlin.gradle.tasks.KotlinCompile +plugins { + alias(libs.plugins.kotlin.jvm) +} + subprojects { apply(plugin = "kotlin") apply(plugin = "application") - dependencies { - add("implementation", "com.github.ajalt.clikt:clikt:4.3.0") - } - tasks.withType().configureEach { kotlinOptions { freeCompilerArgs = freeCompilerArgs + "-opt-in=kotlin.RequiresOptIn" } } + + tasks.withType().configureEach { + useJUnitPlatform() + } } diff --git a/tools/mklanguages/build.gradle.kts b/tools/mklanguages/build.gradle.kts index 9e744aa7b..ce5b37fd0 100644 --- a/tools/mklanguages/build.gradle.kts +++ b/tools/mklanguages/build.gradle.kts @@ -15,26 +15,15 @@ * see . */ +plugins { + alias(libs.plugins.pachli.tool) +} + application { mainClass = "app.pachli.mklanguages.MainKt" } dependencies { - // ICU - implementation("com.ibm.icu:icu4j:74.2") - - // Parsing - implementation("com.github.h0tk3y.betterParse:better-parse:0.4.4") - - // Logging - implementation("io.github.oshai:kotlin-logging-jvm:6.0.4") - implementation("ch.qos.logback:logback-classic:1.5.3") - - // Testing - testImplementation(kotlin("test")) - testImplementation("org.junit.jupiter:junit-jupiter-params:5.10.2") // for parameterized tests -} - -tasks.test { - useJUnitPlatform() + implementation(libs.betterparse) + implementation(libs.icu4j) } diff --git a/checks/settings.gradle.kts b/tools/mklanguages/src/test/kotlin/app/pachli/mklanguages/AppTest.kt similarity index 65% rename from checks/settings.gradle.kts rename to tools/mklanguages/src/test/kotlin/app/pachli/mklanguages/AppTest.kt index 76e19bb85..139f6b5c8 100644 --- a/checks/settings.gradle.kts +++ b/tools/mklanguages/src/test/kotlin/app/pachli/mklanguages/AppTest.kt @@ -1,5 +1,5 @@ /* - * Copyright 2023 Pachli Association + * Copyright 2024 Pachli Association * * This file is a part of Pachli. * @@ -15,16 +15,17 @@ * see . */ -dependencyResolutionManagement { - repositories { - google() - mavenCentral() - } - versionCatalogs { - create("libs") { - from(files("../gradle/libs.versions.toml")) - } +package app.pachli.mklanguages + +import com.github.ajalt.clikt.testing.test +import com.google.common.truth.Truth.assertThat +import org.junit.jupiter.api.Test + +class AppTest { + @Test + fun testHelp() { + val app = App() + val result = app.test("--help") + assertThat(result.statusCode).isEqualTo(0) } } - -rootProject.name = "checks" diff --git a/tools/mklanguages/src/test/kotlin/app/pachli/mklanguages/ValuesParserTest.kt b/tools/mklanguages/src/test/kotlin/app/pachli/mklanguages/ValuesParserTest.kt index 38228235a..75295a7d3 100644 --- a/tools/mklanguages/src/test/kotlin/app/pachli/mklanguages/ValuesParserTest.kt +++ b/tools/mklanguages/src/test/kotlin/app/pachli/mklanguages/ValuesParserTest.kt @@ -18,8 +18,8 @@ package app.pachli.mklanguages import com.github.h0tk3y.betterParse.grammar.parseToEnd +import com.google.common.truth.Truth.assertThat import java.util.stream.Stream -import org.junit.jupiter.api.Assertions.assertEquals import org.junit.jupiter.api.Nested import org.junit.jupiter.api.parallel.Execution import org.junit.jupiter.api.parallel.ExecutionMode @@ -49,7 +49,7 @@ internal class ValuesParserTest { @ParameterizedTest @MethodSource("getParams") fun `returns the expected locale`(params: Params) { - assertEquals(params.expected, parser.parseToEnd(params.filename).locale) + assertThat(parser.parseToEnd(params.filename).locale).isEqualTo(params.expected) } } } diff --git a/tools/mkserverversions/build.gradle.kts b/tools/mkserverversions/build.gradle.kts index 66b3ecd7e..d88845a74 100644 --- a/tools/mkserverversions/build.gradle.kts +++ b/tools/mkserverversions/build.gradle.kts @@ -18,6 +18,7 @@ plugins { alias(libs.plugins.google.ksp) alias(libs.plugins.apollographql) + alias(libs.plugins.pachli.tool) } application { @@ -25,24 +26,10 @@ application { } dependencies { - // GraphQL client implementation(libs.apollo.runtime) - // Logging - implementation("io.github.oshai:kotlin-logging-jvm:6.0.4") - implementation("ch.qos.logback:logback-classic:1.5.3") - - // Moshi implementation(libs.moshi) ksp(libs.moshi.codegen) - - // Testing - testImplementation(kotlin("test")) - testImplementation("org.junit.jupiter:junit-jupiter-params:5.10.2") // for parameterized tests -} - -tasks.test { - useJUnitPlatform() } apollo { diff --git a/tools/mklanguages/settings.gradle.kts b/tools/mkserverversions/src/test/kotlin/app/pachli/mkserverversions/AppTest.kt similarity index 65% rename from tools/mklanguages/settings.gradle.kts rename to tools/mkserverversions/src/test/kotlin/app/pachli/mkserverversions/AppTest.kt index 56f78cb51..3929d161f 100644 --- a/tools/mklanguages/settings.gradle.kts +++ b/tools/mkserverversions/src/test/kotlin/app/pachli/mkserverversions/AppTest.kt @@ -1,5 +1,5 @@ /* - * Copyright 2023 Pachli Association + * Copyright 2024 Pachli Association * * This file is a part of Pachli. * @@ -15,16 +15,17 @@ * see . */ -dependencyResolutionManagement { - repositories { - google() - mavenCentral() - } - versionCatalogs { - create("libs") { - from(files("../../gradle/libs.versions.toml")) - } +package app.pachli.mkserverversions + +import com.github.ajalt.clikt.testing.test +import com.google.common.truth.Truth +import org.junit.jupiter.api.Test + +class AppTest { + @Test + fun testHelp() { + val app = App() + val result = app.test("--help") + Truth.assertThat(result.statusCode).isEqualTo(0) } } - -rootProject.name = "mklanguages" diff --git a/tools/mvstring/build.gradle.kts b/tools/mvstring/build.gradle.kts index dc71a97c9..f46a79c7e 100644 --- a/tools/mvstring/build.gradle.kts +++ b/tools/mvstring/build.gradle.kts @@ -15,20 +15,10 @@ * see . */ +plugins { + alias(libs.plugins.pachli.tool) +} + application { mainClass = "app.pachli.mvstring.MainKt" } - -dependencies { - // Logging - implementation("io.github.oshai:kotlin-logging-jvm:6.0.4") - implementation("ch.qos.logback:logback-classic:1.5.3") - - // Testing - testImplementation(kotlin("test")) - testImplementation("org.junit.jupiter:junit-jupiter-params:5.10.2") // for parameterized tests -} - -tasks.test { - useJUnitPlatform() -} diff --git a/tools/mvstring/settings.gradle.kts b/tools/mvstring/settings.gradle.kts deleted file mode 100644 index ab3455738..000000000 --- a/tools/mvstring/settings.gradle.kts +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Copyright 2023 Pachli Association - * - * This file is a part of Pachli. - * - * This program is free software; you can redistribute it and/or modify it under the terms of the - * GNU General Public License as published by the Free Software Foundation; either version 3 of the - * License, or (at your option) any later version. - * - * Pachli is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even - * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General - * Public License for more details. - * - * You should have received a copy of the GNU General Public License along with Pachli; if not, - * see . - */ - -dependencyResolutionManagement { - repositories { - google() - mavenCentral() - } - versionCatalogs { - create("libs") { - from(files("../../gradle/libs.versions.toml")) - } - } -} - -rootProject.name = "mvstring" diff --git a/tools/mkserverversions/settings.gradle.kts b/tools/mvstring/src/test/kotlin/app/pachli/mvstring/AppTest.kt similarity index 69% rename from tools/mkserverversions/settings.gradle.kts rename to tools/mvstring/src/test/kotlin/app/pachli/mvstring/AppTest.kt index ca0d9fd86..f39a94c59 100644 --- a/tools/mkserverversions/settings.gradle.kts +++ b/tools/mvstring/src/test/kotlin/app/pachli/mvstring/AppTest.kt @@ -15,16 +15,17 @@ * see . */ -dependencyResolutionManagement { - repositories { - google() - mavenCentral() - } - versionCatalogs { - create("libs") { - from(files("../../gradle/libs.versions.toml")) - } +package app.pachli.mvstring + +import com.github.ajalt.clikt.testing.test +import com.google.common.truth.Truth +import org.junit.jupiter.api.Test + +class AppTest { + @Test + fun testHelp() { + val app = App() + val result = app.test("--help") + Truth.assertThat(result.statusCode).isEqualTo(0) } } - -rootProject.name = "mkserverversions"