diff --git a/.github/workflows/buildSrc.yml b/.github/workflows/buildSrc.yml new file mode 100644 index 0000000000..4d86146a6d --- /dev/null +++ b/.github/workflows/buildSrc.yml @@ -0,0 +1,26 @@ +# Ensures that `buildSrc` directories are the same in all 3 projects: +# - the root project; +# - smoke tests; +# - the `base-validating-builders` project. + +name: Check buildSrc copies + +on: + pull_request: + branches: + - master + +jobs: + build: + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v1 + + - name: Check root and `smoke-tests` copies are the same. + shell: bash + run: ./script/same-dir.sh ./buildSrc ./tools/smoke-tests/buildSrc + + - name: Check root and `base-validating-builders` copies are the same. + shell: bash + run: ./script/same-dir.sh ./buildSrc ./base-validating-builders/buildSrc diff --git a/README.md b/README.md index aa50632fde..f68124a02f 100644 --- a/README.md +++ b/README.md @@ -33,8 +33,18 @@ The repository also contains: ### Notes on Coverage -Currently the coverage stats reflect the hits gathered from unit tests. However, Gradle plugins - +Currently, the coverage stats reflect the hits gathered from unit tests. However, Gradle plugins - a significant part of this repository - are covered with integration tests. During each of those, a standalone Gradle process is launched. The limitations of `jacoco` task API do not allow to include the coverage of such tests into the repository coverage report easily. Therefore, current coverage percentage shown is significantly lower than a real one. + +### `pull` scripts + +In most Spine repositories, we update the `config` submodule by running `./config/pull` (or its +Batch equivalent). However, in `base` we also need to copy Gradle `buildSrc` directory into included +builds: `smoke-tests` and `base-validating-builders`. Thus, here we have `./pull` and `.\pull.bat` +scripts which do whatever their `config` counterparts do and also copy `buildSrc` into the two +included build directories. + +It is always recommended to run `./pull` instead of `./config/pull`. diff --git a/base-validating-builders/build.gradle b/base-validating-builders/build.gradle deleted file mode 100644 index 4f86242182..0000000000 --- a/base-validating-builders/build.gradle +++ /dev/null @@ -1,147 +0,0 @@ -/* - * Copyright 2020, TeamDev. All rights reserved. - * - * Redistribution and use in source and/or binary forms, with or without - * modification, must retain the above copyright notice and the following - * disclaimer. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -buildscript { - apply from: "$projectDir/../version.gradle.kts" - apply from: "$projectDir/../config/gradle/dependencies.gradle" - - repositories { - mavenLocal() - jcenter() - } - dependencies { - classpath deps.build.protobuf - classpath deps.build.guava - classpath deps.build.flogger - classpath deps.build.checkerAnnotations - classpath deps.build.errorProneAnnotations - classpath deps.build.jsr305Annotations - classpath deps.build.gradlePlugins.protobuf - - classpath deps.gen.javaPoet - classpath deps.runtime.floggerSystemBackend - - // A library for parsing Java sources. - // Used for parsing Java sources generated from Protobuf files - // to make their annotation more convenient. - classpath (deps.build.roasterApi) { - exclude group: 'com.google.guava' - } - classpath (deps.build.roasterJdt) { - exclude group: 'com.google.guava' - } - - classpath files([ - "$projectDir/../tools/protoc-api/build/libs/protoc-api-${spineVersion}.jar", - "$projectDir/../tools/model-compiler/build/libs/model-compiler-${spineVersion}.jar", - "$projectDir/../tools/plugin-base/build/libs/plugin-base-${spineVersion}.jar", - "$projectDir/../tools/tool-base/build/libs/tool-base-${spineVersion}.jar", - "$projectDir/../base/build/libs/base-${spineVersion}.jar", - ]) - } -} - -apply plugin: 'java' -apply plugin: 'com.google.protobuf' -apply plugin: 'io.spine.tools.spine-model-compiler' -apply plugin: 'idea' - -modelCompiler { - generateValidation = true -} - -repositories { - // This defines the `libs` directory of upstream projects as a local repository. - // See `dependencies` section below for definition of the dependency on the JAR produced by - // the `base` module. - flatDir { - final def baseRoot = "$projectDir/.." - dirs "$baseRoot/base/build/libs/" - } - mavenLocal() - jcenter() -} - -dependencies { - compileOnly deps.build.protobuf - compileOnly deps.build.guava - compileOnly deps.build.flogger - compileOnly deps.build.checkerAnnotations - compileOnly deps.build.errorProneAnnotations - compileOnly deps.build.jsr305Annotations - compileOnly deps.build.errorProneAnnotations - - // The below dependency refers to a local artifact. - // See `repositories.flatDir` definition above. - compileOnly name: "base-${spineVersion}" -} - -sourceSets { - main.java.srcDirs "$projectDir/generated/main/spine" - main.proto.srcDirs = ["$projectDir/../base/src/main/proto"] -} - -protobuf { - generateProtoTasks { - all().each { - it.plugins { - remove grpc - } - } - } -} - -ext.compiledProtoDir = "$projectDir/compiled-proto" - -task copyCompiledClasses(type: Copy) { - from sourceSets.main.java.outputDir - into compiledProtoDir - - include { - it.isDirectory() || it.name.endsWith('.class') - } - - dependsOn compileJava -} - -assemble.dependsOn copyCompiledClasses - -build.doLast { - final def directory = "$projectDir/../" - final def runsOnWindows = org.gradle.internal.os.OperatingSystem.current().isWindows() - final def script = runsOnWindows ? "gradlew.bat" : "gradlew" - final def process = new ProcessBuilder() - .command("$directory/$script".toString(), ':base:cleanJar', ':base:jar', '--console=plain') - .directory(file(directory)) - .start() - if (process.waitFor() != 0) { - throw new GradleException("Unable to rebuild JAR for :base.") - } -} - -task cleanGenerated(type: Delete) { - delete files("$projectDir/generated", "$projectDir/.spine", compiledProtoDir) -} - -clean.dependsOn cleanGenerated - -idea.module { - generatedSourceDirs += compiledProtoDir -} diff --git a/base-validating-builders/build.gradle.kts b/base-validating-builders/build.gradle.kts new file mode 100644 index 0000000000..7fbe82f7b8 --- /dev/null +++ b/base-validating-builders/build.gradle.kts @@ -0,0 +1,170 @@ +/* + * Copyright 2020, TeamDev. All rights reserved. + * + * Redistribution and use in source and/or binary forms, with or without + * modification, must retain the above copyright notice and the following + * disclaimer. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +import com.google.protobuf.gradle.ProtobufConfigurator.JavaGenerateProtoTaskCollection +import com.google.protobuf.gradle.* +import io.spine.gradle.internal.Deps +import org.gradle.internal.os.OperatingSystem + +buildscript { + apply(from = "$projectDir/../version.gradle.kts") + val spineVersion: String by extra + + repositories { + mavenLocal() + jcenter() + } + + @Suppress("RemoveRedundantQualifierName") // Cannot use imports here. + val deps = io.spine.gradle.internal.Deps + + dependencies { + deps.build.protobuf.forEach { classpath(it) } + classpath(deps.build.guava) + classpath(deps.build.flogger) + classpath(deps.build.checkerAnnotations) + deps.build.errorProneAnnotations.forEach { classpath(it) } + classpath(deps.build.jsr305Annotations) + classpath(deps.build.gradlePlugins.protobuf) + + classpath(deps.gen.javaPoet) + classpath(deps.runtime.flogger.systemBackend) + + // A library for parsing Java sources. + // Used for parsing Java sources generated from Protobuf files + // to make their annotation more convenient. + classpath(deps.build.roasterApi) { + exclude(group = "com.google.guava") + } + classpath (deps.build.roasterJdt) { + exclude(group = "com.google.guava") + } + + classpath(files( + "$projectDir/../tools/protoc-api/build/libs/protoc-api-${spineVersion}.jar", + "$projectDir/../tools/model-compiler/build/libs/model-compiler-${spineVersion}.jar", + "$projectDir/../tools/plugin-base/build/libs/plugin-base-${spineVersion}.jar", + "$projectDir/../tools/tool-base/build/libs/tool-base-${spineVersion}.jar", + "$projectDir/../base/build/libs/base-${spineVersion}.jar" + )) + } +} + +plugins { + java + idea + @Suppress("RemoveRedundantQualifierName") // Cannot use imports here. + id("com.google.protobuf").version(io.spine.gradle.internal.Deps.versions.protobufPlugin) +} + +apply(plugin = "io.spine.tools.spine-model-compiler") + +extensions["modelCompiler"].withGroovyBuilder { + setProperty("generateValidation", true) +} + +repositories { + // This defines the `libs` directory of upstream projects as a local repository. + // See `dependencies` section below for definition of the dependency on the JAR produced by + // the `base` module. + flatDir { + val baseRoot = "$projectDir/.." + dir("$baseRoot/base/build/libs/") + } + mavenLocal() + jcenter() +} + +val spineVersion: String by extra + +dependencies { + Deps.build.protobuf.forEach { compileOnly(it) } + compileOnly(Deps.build.guava) + compileOnly(Deps.build.flogger) + compileOnly(Deps.build.checkerAnnotations) + Deps.build.errorProneAnnotations.forEach { compileOnly(it) } + compileOnly(Deps.build.jsr305Annotations) + + // The below dependency refers to a local artifact. + // See `repositories.flatDir` definition above. + compileOnly(name = "base-${spineVersion}", group = "") +} + +sourceSets { + main { + java.srcDirs("$projectDir/generated/main/spine") + proto.srcDirs("$projectDir/../base/src/main/proto") + } +} + +protobuf { + generateProtoTasks { + all().forEach { task -> + task.plugins { + remove("grpc") + } + } + } +} + +val compiledProtoDir = "$projectDir/compiled-proto" + +val copyCompiledClasses by tasks.registering(Copy::class) { + from(sourceSets.main.get().java.outputDir) + into(compiledProtoDir) + + include { + it.isDirectory || it.name.endsWith(".class") + } + + dependsOn(tasks.compileJava) +} + +tasks.assemble { + dependsOn(copyCompiledClasses) +} + +tasks.build { + doLast { + val directory = "$projectDir/../" + val os = OperatingSystem.current() + val script = when { + os.isWindows -> "gradlew.bat" + else -> "gradlew" + } + val process = ProcessBuilder() + .command("$directory/$script", ":base:cleanJar", ":base:jar", "--console=plain") + .directory(file(directory)) + .start() + if (process.waitFor() != 0) { + throw GradleException("Unable to rebuild JAR for :base.") + } + } +} + +val cleanGenerated by tasks.registering(Delete::class) { + delete(files("$projectDir/generated", "$projectDir/.spine", compiledProtoDir)) +} + +tasks.clean { dependsOn(cleanGenerated) } + +idea.module { + generatedSourceDirs.add(file(compiledProtoDir)) +} diff --git a/base-validating-builders/buildSrc/build.gradle.kts b/base-validating-builders/buildSrc/build.gradle.kts new file mode 100644 index 0000000000..7dc929afca --- /dev/null +++ b/base-validating-builders/buildSrc/build.gradle.kts @@ -0,0 +1,36 @@ +/* + * Copyright 2020, TeamDev. All rights reserved. + * + * Redistribution and use in source and/or binary forms, with or without + * modification, must retain the above copyright notice and the following + * disclaimer. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +plugins { + // Use Kotlin for `buildSrc`. + // https://kotlinlang.org/docs/reference/using-gradle.html#targeting-the-jvm + kotlin("jvm").version("1.3.72") +} + +repositories { + mavenLocal() + jcenter() +} + +val jacksonVersion = "2.11.0" + +dependencies { + implementation("com.fasterxml.jackson.dataformat:jackson-dataformat-xml:$jacksonVersion") +} diff --git a/base-validating-builders/buildSrc/src/main/kotlin/io/spine/gradle/internal/CheckVersionIncrement.kt b/base-validating-builders/buildSrc/src/main/kotlin/io/spine/gradle/internal/CheckVersionIncrement.kt new file mode 100644 index 0000000000..60709874e8 --- /dev/null +++ b/base-validating-builders/buildSrc/src/main/kotlin/io/spine/gradle/internal/CheckVersionIncrement.kt @@ -0,0 +1,104 @@ +/* + * Copyright 2020, TeamDev. All rights reserved. + * + * Redistribution and use in source and/or binary forms, with or without + * modification, must retain the above copyright notice and the following + * disclaimer. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package io.spine.gradle.internal + +import com.fasterxml.jackson.databind.DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES +import com.fasterxml.jackson.dataformat.xml.XmlMapper +import org.gradle.api.GradleException +import org.gradle.api.Project +import org.gradle.api.internal.AbstractTask +import org.gradle.api.tasks.Input +import org.gradle.api.tasks.TaskAction +import java.net.URL + +/** + * A task which verifies that the current version of the library has not been published to the given + * Maven repository yet. + */ +open class CheckVersionIncrement : AbstractTask() { + + /** + * The Maven repository in which to look for published artifacts. + * + * We only check the `releases` repository. Artifacts in `snapshots` repository still may be + * overridden. + */ + @Input + lateinit var repository: Repository + + @Input + private val version: String = project.version as String + + @TaskAction + private fun fetchAndCheck() { + val artifact = "${project.artifactPath()}/${MavenMetadata.FILE_NAME}" + val repoUrl = repository.releases + val metadata = fetch(repoUrl, artifact) + val versions = metadata.versioning.versions + val versionExists = versions.contains(version) + if (versionExists) { + throw GradleException(""" + Version `$version` is already published to maven repository `$repoUrl`. + Try incrementing the library version. + All available versions are: ${versions.joinToString(separator = ", ")}. + + To disable this check, run Gradle with `-x $name`. + """.trimIndent() + ) + } + } + + private fun fetch(repository: String, artifact: String): MavenMetadata { + val url = URL("$repository/$artifact") + return MavenMetadata.fetchAndParse(url) + } + + private fun Project.artifactPath(): String { + val group = this.group as String + val name = "spine-${this.name}" + + val pathElements = ArrayList(group.split('.')) + pathElements.add(name) + val path = pathElements.joinToString(separator = "/") + return path + } +} + +private data class MavenMetadata(var versioning: Versioning = Versioning()) { + + companion object { + + const val FILE_NAME = "maven-metadata.xml" + + private val mapper = XmlMapper() + + init { + mapper.configure(FAIL_ON_UNKNOWN_PROPERTIES, false) + } + + fun fetchAndParse(url: URL): MavenMetadata { + val metadata = mapper.readValue(url, MavenMetadata::class.java) + return metadata + } + } +} + +private data class Versioning(var versions: List = listOf()) diff --git a/base-validating-builders/buildSrc/src/main/kotlin/io/spine/gradle/internal/IncrementGuard.kt b/base-validating-builders/buildSrc/src/main/kotlin/io/spine/gradle/internal/IncrementGuard.kt new file mode 100644 index 0000000000..c227f49889 --- /dev/null +++ b/base-validating-builders/buildSrc/src/main/kotlin/io/spine/gradle/internal/IncrementGuard.kt @@ -0,0 +1,46 @@ +/* + * Copyright 2020, TeamDev. All rights reserved. + * + * Redistribution and use in source and/or binary forms, with or without + * modification, must retain the above copyright notice and the following + * disclaimer. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package io.spine.gradle.internal + +import org.gradle.api.Plugin +import org.gradle.api.Project + +/** + * Gradle plugin which adds a [CheckVersionIncrement] task. + * + * The task is called `checkVersionIncrement` inserted before the `check` task. + */ +class IncrementGuard : Plugin { + + companion object { + const val taskName = "checkVersionIncrement" + } + + override fun apply(target: Project) { + val tasks = target.tasks + tasks.register(taskName, CheckVersionIncrement::class.java) { + it.repository = PublishingRepos.cloudRepo + tasks.getByName("check").dependsOn(it) + + it.shouldRunAfter("test") + } + } +} diff --git a/base-validating-builders/buildSrc/src/main/kotlin/io/spine/gradle/internal/RunBuild.kt b/base-validating-builders/buildSrc/src/main/kotlin/io/spine/gradle/internal/RunBuild.kt new file mode 100644 index 0000000000..c083ad952a --- /dev/null +++ b/base-validating-builders/buildSrc/src/main/kotlin/io/spine/gradle/internal/RunBuild.kt @@ -0,0 +1,90 @@ +/* + * Copyright 2020, TeamDev. All rights reserved. + * + * Redistribution and use in source and/or binary forms, with or without + * modification, must retain the above copyright notice and the following + * disclaimer. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package io.spine.gradle.internal + +import org.gradle.api.GradleException +import org.gradle.api.internal.AbstractTask +import org.gradle.api.tasks.TaskAction +import org.gradle.internal.os.OperatingSystem +import java.io.File + +/** + * A Gradle task which runs another Gradle build. + * + * Launches Gradle wrapper under a given [directory] with the `build` task. The `clean` task is also + * run if current build includes a `clean` task. + * + * The build writes verbose log into `$directory/build/debug-out.txt`. The error output is written + * into `$directory/build/error-out.txt`. + */ +open class RunBuild : AbstractTask() { + + /** + * Path to the directory which contains a Gradle wrapper script. + */ + lateinit var directory: String + + @TaskAction + private fun execute() { + val runsOnWindows = OperatingSystem.current().isWindows() + val script = if (runsOnWindows) "gradlew.bat" else "gradlew" + val command = buildCommand(script) + + // Ensure build error output log. + // Since we're executing this task in another process, we redirect error output to + // the file under the `build` directory. + val buildDir = File(directory, "build") + if (!buildDir.exists()) { + buildDir.mkdir() + } + val errorOut = File(buildDir, "error-out.txt") + val debugOut = File(buildDir, "debug-out.txt") + + val process = buildProcess(command, errorOut, debugOut) + if (process.waitFor() != 0) { + throw GradleException("Build FAILED. See $errorOut for details.") + } + } + + private fun buildCommand(script: String): List { + val command = mutableListOf() + command.add("${project.rootDir}/$script") + val shouldClean = project.gradle + .taskGraph + .hasTask(":clean") + if (shouldClean) { + command.add("clean") + } + command.add("build") + command.add("--console=plain") + command.add("--debug") + command.add("--stacktrace") + return command + } + + private fun buildProcess(command: List, errorOut: File, debugOut: File) = + ProcessBuilder() + .command(command) + .directory(project.file(directory)) + .redirectError(errorOut) + .redirectOutput(debugOut) + .start() +} diff --git a/base-validating-builders/buildSrc/src/main/kotlin/io/spine/gradle/internal/deps.kt b/base-validating-builders/buildSrc/src/main/kotlin/io/spine/gradle/internal/deps.kt new file mode 100644 index 0000000000..2636036af2 --- /dev/null +++ b/base-validating-builders/buildSrc/src/main/kotlin/io/spine/gradle/internal/deps.kt @@ -0,0 +1,345 @@ +/* + * Copyright 2020, TeamDev. All rights reserved. + * + * Redistribution and use in source and/or binary forms, with or without + * modification, must retain the above copyright notice and the following + * disclaimer. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package io.spine.gradle.internal + +import org.gradle.api.Project +import org.gradle.api.artifacts.ConfigurationContainer +import org.gradle.api.artifacts.dsl.RepositoryHandler +import java.net.URI + +/* + * This file describes shared dependencies of Spine sub-projects. + * + * Inspired by dependency management of the Uber's NullAway project: + * https://github.com/uber/NullAway/blob/master/gradle/dependencies.gradle + */ + +data class Repository(val releases: String, + val snapshots: String, + val credentials: String) + +/** + * Repositories to which we may publish. Normally, only one repository will be used. + * + * See `publish.gradle` for details of the publishing process. + */ +object PublishingRepos { + val mavenTeamDev = Repository( + releases = "http://maven.teamdev.com/repository/spine", + snapshots = "http://maven.teamdev.com/repository/spine-snapshots", + credentials = "credentials.properties" + ) + val cloudRepo = Repository( + releases = "https://spine.mycloudrepo.io/public/repositories/releases", + snapshots = "https://spine.mycloudrepo.io/public/repositories/snapshots", + credentials = "cloudrepo.properties" + ) +} + +// Specific repositories. +object Repos { + val oldSpine: String = PublishingRepos.mavenTeamDev.releases + val oldSpineSnapshots: String = PublishingRepos.mavenTeamDev.snapshots + + val spine: String = PublishingRepos.cloudRepo.releases + val spineSnapshots: String = PublishingRepos.cloudRepo.snapshots + + val sonatypeSnapshots: String = "https://oss.sonatype.org/content/repositories/snapshots" + val gradlePlugins = "https://plugins.gradle.org/m2/" +} + +object Versions { + val checkerFramework = "3.3.0" + val errorProne = "2.3.4" + val errorProneJavac = "9+181-r4173-1" // taken from here: https://github.com/tbroyer/gradle-errorprone-plugin/blob/v0.8/build.gradle.kts + val errorPronePlugin = "1.1.1" + val pmd = "6.20.0" + val checkstyle = "8.29" + val protobufPlugin = "0.8.12" + val appengineApi = "1.9.79" + val appenginePlugin = "2.2.0" + val findBugs = "3.0.2" + val guava = "29.0-jre" + val protobuf = "3.11.4" + val grpc = "1.28.1" + val flogger = "0.5.1" + val junit4 = "4.12" + val junit5 = "5.6.2" + val junitPlatform = "1.6.2" + val junitPioneer = "0.4.2" + val truth = "1.0.1" + val httpClient = "1.34.2" + val apacheHttpClient = "2.1.2" + val firebaseAdmin = "6.12.2" + val roaster = "2.21.2.Final" + val licensePlugin = "1.13" + val javaPoet = "1.12.1" + val autoService = "1.0-rc6" + val autoCommon = "0.10" + val jackson = "2.9.10.4" + val animalSniffer = "1.18" + val apiguardian = "1.1.0" + + /** + * Version of the SLF4J library. + * + * Spine used to log with SLF4J. Now we use Flogger. Whenever a coice comes up, we recommend to + * use the latter. + * + * Some third-party libraries may clash with different versions of the library. Thus, we specify + * this version and force it via [forceConfiguration(..)][DependencyResolution.forceConfiguration]. + */ + @Deprecated("Use Flogger over SLF4J.", replaceWith = ReplaceWith("flogger")) + val slf4j = "1.7.29" +} + +object GradlePlugins { + val errorProne = "net.ltgt.gradle:gradle-errorprone-plugin:${Versions.errorPronePlugin}" + val protobuf = "com.google.protobuf:protobuf-gradle-plugin:${Versions.protobufPlugin}" + val appengine = "com.google.cloud.tools:appengine-gradle-plugin:${Versions.appenginePlugin}" + val licenseReport = "com.github.jk1:gradle-license-report:${Versions.licensePlugin}" +} + +object Build { + val errorProneJavac = "com.google.errorprone:javac:${Versions.errorProneJavac}" + val errorProneAnnotations = listOf( + "com.google.errorprone:error_prone_annotations:${Versions.errorProne}", + "com.google.errorprone:error_prone_type_annotations:${Versions.errorProne}" + ) + val errorProneCheckApi = "com.google.errorprone:error_prone_check_api:${Versions.errorProne}" + val errorProneCore = "com.google.errorprone:error_prone_core:${Versions.errorProne}" + val errorProneTestHelpers = "com.google.errorprone:error_prone_test_helpers:${Versions.errorProne}" + val checkerAnnotations = "org.checkerframework:checker-qual:${Versions.checkerFramework}" + val checkerDataflow = listOf( + "org.checkerframework:dataflow:${Versions.checkerFramework}", + "org.checkerframework:javacutil:${Versions.checkerFramework}" + ) + val autoCommon = "com.google.auto:auto-common:${Versions.autoCommon}" + val autoService = AutoService + val jsr305Annotations = "com.google.code.findbugs:jsr305:${Versions.findBugs}" + val guava = "com.google.guava:guava:${Versions.guava}" + val flogger = "com.google.flogger:flogger:${Versions.flogger}" + val protobuf = listOf( + "com.google.protobuf:protobuf-java:${Versions.protobuf}", + "com.google.protobuf:protobuf-java-util:${Versions.protobuf}" + ) + val protoc = "com.google.protobuf:protoc:${Versions.protobuf}" + val googleHttpClient = "com.google.http-client:google-http-client:${Versions.httpClient}" + val googleHttpClientApache = "com.google.http-client:google-http-client-apache:${Versions.apacheHttpClient}" + val appengineApi = "com.google.appengine:appengine-api-1.0-sdk:${Versions.appengineApi}" + val firebaseAdmin = "com.google.firebase:firebase-admin:${Versions.firebaseAdmin}" + val jacksonDatabind = "com.fasterxml.jackson.core:jackson-databind:${Versions.jackson}" + val roasterApi = "org.jboss.forge.roaster:roaster-api:${Versions.roaster}" + val roasterJdt = "org.jboss.forge.roaster:roaster-jdt:${Versions.roaster}" + val animalSniffer = "org.codehaus.mojo:animal-sniffer-annotations:${Versions.animalSniffer}" + val ci = "true".equals(System.getenv("CI")) + val gradlePlugins = GradlePlugins + @Deprecated("Use Flogger over SLF4J.", replaceWith = ReplaceWith("flogger")) + @Suppress("DEPRECATION") // Version of SLF4J. + val slf4j = "org.slf4j:slf4j-api:${Versions.slf4j}" + + object AutoService { + val annotations = "com.google.auto.service:auto-service-annotations:${Versions.autoService}" + val processor = "com.google.auto.service:auto-service:${Versions.autoService}" + } +} + +object Gen { + val javaPoet = "com.squareup:javapoet:${Versions.javaPoet}" +} + +object Grpc { + val core = "io.grpc:grpc-core:${Versions.grpc}" + val stub = "io.grpc:grpc-stub:${Versions.grpc}" + val okHttp = "io.grpc:grpc-okhttp:${Versions.grpc}" + val protobuf = "io.grpc:grpc-protobuf:${Versions.grpc}" + val netty = "io.grpc:grpc-netty:${Versions.grpc}" + val nettyShaded = "io.grpc:grpc-netty-shaded:${Versions.grpc}" + val context = "io.grpc:grpc-context:${Versions.grpc}" + + @Deprecated("Use the shorter form.", replaceWith = ReplaceWith("core")) + val grpcCore = core + @Deprecated("Use the shorter form.", replaceWith = ReplaceWith("stub")) + val grpcStub = stub + @Deprecated("Use the shorter form.", replaceWith = ReplaceWith("okHttp")) + val grpcOkHttp = okHttp + @Deprecated("Use the shorter form.", replaceWith = ReplaceWith("protobuf")) + val grpcProtobuf = protobuf + @Deprecated("Use the shorter form.", replaceWith = ReplaceWith("netty")) + val grpcNetty = netty + @Deprecated("Use the shorter form.", replaceWith = ReplaceWith("nettyShaded")) + val grpcNettyShaded = nettyShaded + @Deprecated("Use the shorter form.", replaceWith = ReplaceWith("context")) + val grpcContext = context +} + +object Runtime { + + val flogger = Flogger + + object Flogger { + val systemBackend = "com.google.flogger:flogger-system-backend:${Versions.flogger}" + val log4J = "com.google.flogger:flogger-log4j:${Versions.flogger}" + val slf4J = "com.google.flogger:slf4j-backend-factory:${Versions.flogger}" + } + + @Deprecated("Use the `flogger` object.", replaceWith = ReplaceWith("flogger.systemBackend")) + val floggerSystemBackend = flogger.systemBackend + @Deprecated("Use the `flogger` object.", replaceWith = ReplaceWith("flogger.log4J")) + val floggerLog4J = flogger.log4J + @Deprecated("Use the `flogger` object.", replaceWith = ReplaceWith("flogger.slf4J")) + val floggerSlf4J = flogger.slf4J +} + +object Test { + val junit4 = "junit:junit:${Versions.junit4}" + val junit5Api = listOf( + "org.junit.jupiter:junit-jupiter-api:${Versions.junit5}", + "org.junit.jupiter:junit-jupiter-params:${Versions.junit5}", + "org.apiguardian:apiguardian-api:${Versions.apiguardian}" + ) + val junit5Runner = "org.junit.jupiter:junit-jupiter-engine:${Versions.junit5}" + val junitPioneer = "org.junit-pioneer:junit-pioneer:${Versions.junitPioneer}" + val guavaTestlib = "com.google.guava:guava-testlib:${Versions.guava}" + val mockito = "org.mockito:mockito-core:2.12.0" + val hamcrest = "org.hamcrest:hamcrest-all:1.3" + val truth = listOf( + "com.google.truth:truth:${Versions.truth}", + "com.google.truth.extensions:truth-java8-extension:${Versions.truth}", + "com.google.truth.extensions:truth-proto-extension:${Versions.truth}" + ) + @Deprecated("Use Flogger over SLF4J.", + replaceWith = ReplaceWith("Deps.runtime.floggerSystemBackend")) + @Suppress("DEPRECATION") // Version of SLF4J. + val slf4j = "org.slf4j:slf4j-jdk14:${Versions.slf4j}" +} + +object Scripts { + + private const val COMMON_PATH = "/config/gradle/" + + fun testArtifacts(p: Project) = p.script("test-artifacts.gradle") + fun testOutput(p: Project) = p.script("test-output.gradle") + fun slowTests(p: Project) = p.script("slow-tests.gradle") + fun javadocOptions(p: Project) = p.script("javadoc-options.gradle") + fun filterInternalJavadocs(p: Project) = p.script("filter-internal-javadoc.gradle") + fun jacoco(p: Project) = p.script("jacoco.gradle") + fun publish(p: Project) = p.script("publish.gradle") + fun publishProto(p: Project) = p.script("publish-proto.gradle") + fun javacArgs(p: Project) = p.script("javac-args.gradle") + fun jsBuildTasks(p: Project) = p.script("js/build-tasks.gradle") + fun jsConfigureProto(p: Project) = p.script("js/configure-proto.gradle") + fun npmPublishTasks(p: Project) = p.script("js/npm-publish-tasks.gradle") + fun npmCli(p: Project) = p.script("js/npm-cli.gradle") + fun updatePackageVersion(p: Project) = p.script("js/update-package-version.gradle") + fun dartBuildTasks(p: Project) = p.script("dart/build-tasks.gradle") + fun pubPublishTasks(p: Project) = p.script("dart/pub-publish-tasks.gradle") + fun pmd(p: Project) = p.script("pmd.gradle") + fun checkstyle(p: Project) = p.script("checkstyle.gradle") + fun runBuild(p: Project) = p.script("run-build.gradle") + fun modelCompiler(p: Project) = p.script("model-compiler.gradle") + fun licenseReportCommon(p: Project) = p.script("license-report-common.gradle") + fun projectLicenseReport(p: Project) = p.script("license-report-project.gradle") + fun repoLicenseReport(p: Project) = p.script("license-report-repo.gradle") + fun generatePom(p: Project) = p.script("generate-pom.gradle") + fun updateGitHubPages(p: Project) = p.script("update-gh-pages.gradle") + + private fun Project.script(name: String) = "${rootDir}$COMMON_PATH$name" +} + +object Deps { + val build = Build + val grpc = Grpc + val gen = Gen + val runtime = Runtime + val test = Test + val versions = Versions + val scripts = Scripts +} + +object DependencyResolution { + + fun forceConfiguration(configurations: ConfigurationContainer) { + configurations.all { config -> + config.resolutionStrategy { strategy -> + strategy.failOnVersionConflict() + strategy.cacheChangingModulesFor(0, "seconds") + @Suppress("DEPRECATION") // Force SLF4J version. + strategy.force( + Deps.build.slf4j, + Deps.build.errorProneAnnotations, + Deps.build.jsr305Annotations, + Deps.build.checkerAnnotations, + Deps.build.autoCommon, + Deps.build.guava, + Deps.build.animalSniffer, + Deps.build.protobuf, + Deps.test.guavaTestlib, + Deps.test.truth, + Deps.test.junit5Api, + Deps.test.junit4, + + // Transitive dependencies of 3rd party components that we don't use directly. + "com.google.code.gson:gson:2.8.6", + "com.google.j2objc:j2objc-annotations:1.3", + "org.codehaus.plexus:plexus-utils:3.3.0", + "com.squareup.okio:okio:1.17.5", // Last version before next major. + "commons-cli:commons-cli:1.4", + + // Force discontinued transitive dependency until everybody migrates off it. + "org.checkerframework:checker-compat-qual:2.5.5", + + "commons-logging:commons-logging:1.2", + + // Force the Gradle Protobuf plugin version. + Deps.build.gradlePlugins.protobuf + ) + } + } + } + + fun excludeProtobufLite(configurations: ConfigurationContainer) { + excludeProtoLite(configurations, "runtime") + excludeProtoLite(configurations, "testRuntime") + } + + private fun excludeProtoLite(configurations: ConfigurationContainer, + configurationName: String) { + configurations.named(configurationName).get() + .exclude(mapOf("group" to "com.google.protobuf", "module" to "protobuf-lite")) + } + + fun defaultRepositories(repositories: RepositoryHandler) { + repositories.mavenLocal() + repositories.maven { repository -> + repository.url = URI(Repos.spine) + repository.content { descriptor -> + descriptor.includeGroup("io.spine") + descriptor.includeGroup("io.spine.tools") + descriptor.includeGroup("io.spine.gcloud") + } + } + repositories.jcenter() + repositories.maven { repository -> + repository.url = URI(Repos.gradlePlugins) + } + } +} diff --git a/base-validating-builders/settings.gradle b/base-validating-builders/settings.gradle.kts similarity index 100% rename from base-validating-builders/settings.gradle rename to base-validating-builders/settings.gradle.kts diff --git a/base/build.gradle.kts b/base/build.gradle.kts index ef2db74b57..3762a633fc 100644 --- a/base/build.gradle.kts +++ b/base/build.gradle.kts @@ -18,11 +18,11 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -import com.google.protobuf.gradle.ProtobufConfigurator.JavaGenerateProtoTaskCollection -import groovy.lang.Closure +import com.google.protobuf.gradle.* import groovy.lang.GString import io.spine.gradle.internal.DependencyResolution import io.spine.gradle.internal.Deps +import io.spine.gradle.internal.IncrementGuard import io.spine.gradle.internal.RunBuild import java.nio.file.Files.isSameFile @@ -34,6 +34,7 @@ plugins { group = "io.spine" apply(from = Deps.scripts.testArtifacts(project)) +apply() DependencyResolution.excludeProtobufLite(configurations) @@ -108,24 +109,22 @@ val pruneTestGoogleProtos by tasks.registering(type = Delete::class) { } protobuf { - protobuf.generatedFilesBaseDir = compiledProtoRoot - protobuf.generateProtoTasks(object : Closure(this) { - private fun doCall(tasks: JavaGenerateProtoTaskCollection) { - for (task in tasks.all()) { - val scope = task.sourceSet.name - task.generateDescriptorSet = true - task.descriptorSetOptions.path = GString.EMPTY.plus("$buildDir/descriptors/$scope/known_types_${scope}.desc") - task.descriptorSetOptions.includeImports = true - task.descriptorSetOptions.includeSourceInfo = true - - if (scope.contains("test")) { - pruneTestGoogleProtos.configure { dependsOn(task) } - } else { - pruneGoogleProtos.configure { dependsOn(task) } - } + generatedFilesBaseDir = compiledProtoRoot + generateProtoTasks { + for (task in all()) { + val scope = task.sourceSet.name + task.generateDescriptorSet = true + task.descriptorSetOptions.path = GString.EMPTY.plus("$buildDir/descriptors/$scope/known_types_${scope}.desc") + task.descriptorSetOptions.includeImports = true + task.descriptorSetOptions.includeSourceInfo = true + + if (scope.contains("test")) { + pruneTestGoogleProtos.configure { dependsOn(task) } + } else { + pruneGoogleProtos.configure { dependsOn(task) } } } - }) + } } /** diff --git a/base/src/main/java/io/spine/io/Files2.java b/base/src/main/java/io/spine/io/Files2.java index 8a599b3483..44adb42730 100644 --- a/base/src/main/java/io/spine/io/Files2.java +++ b/base/src/main/java/io/spine/io/Files2.java @@ -20,16 +20,25 @@ package io.spine.io; +import com.google.common.collect.ImmutableList; import com.google.errorprone.annotations.CanIgnoreReturnValue; import java.io.File; import java.io.IOException; +import java.nio.file.Files; import java.nio.file.Path; +import java.util.stream.Stream; +import static com.google.common.base.Preconditions.checkArgument; import static com.google.common.base.Preconditions.checkNotNull; import static com.google.common.base.Preconditions.checkState; +import static com.google.common.collect.ImmutableList.toImmutableList; import static com.google.common.io.Files.createParentDirs; import static io.spine.util.Exceptions.newIllegalArgumentException; +import static java.nio.file.Files.copy; +import static java.nio.file.Files.createDirectory; +import static java.nio.file.Files.isDirectory; +import static java.nio.file.Files.isRegularFile; /** * Additional utilities for working with files. @@ -141,7 +150,8 @@ public static boolean existsNonEmpty(File file) { * Ensures that the passed file exists. * * @return the passed file if it exists - * @throws IllegalStateException if the file is missing + * @throws IllegalStateException + * if the file is missing */ @CanIgnoreReturnValue public static File checkExists(File file) { @@ -149,4 +159,41 @@ public static File checkExists(File file) { checkState(file.exists(), "The file `%s` does not exist.", file); return file; } + + /** + * Copies a whole directory and its contents into another directory. + * + *

Both paths must point to an existing directory. + * + *

The {@code dir} itself is copied as well. For example, if the {@code dir} path is + * {@code /my/path/to/folder/foo} and the {@code target} path is {@code /my/other/folder}, as + * a result of this operation, a {@code /my/other/folder/foo} directory will be created and all + * the contents of the original {@code dir}, including nested directories, will be copied there. + * + * @param dir + * the dir to copy + * @param target + * the new parent directory + */ + public static void copyDir(Path dir, Path target) throws IOException { + checkNotNull(dir); + checkNotNull(target); + checkArgument(isDirectory(dir)); + checkArgument(isDirectory(target)); + + Path oldParent = dir.getParent(); + ImmutableList files; + try (Stream paths = Files.walk(dir)) { + files = paths.collect(toImmutableList()); + } + for (Path file : files) { + Path relative = oldParent.relativize(file); + Path newPath = target.resolve(relative); + if (isDirectory(file)) { + createDirectory(newPath); + } else if (isRegularFile(file)) { + copy(file, newPath); + } + } + } } diff --git a/build.gradle.kts b/build.gradle.kts index 22c5dbcb5d..be3d112419 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -18,6 +18,7 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +import com.google.protobuf.gradle.* import io.spine.gradle.internal.DependencyResolution import io.spine.gradle.internal.Deps import io.spine.gradle.internal.PublishingRepos @@ -28,8 +29,6 @@ buildscript { @Suppress("RemoveRedundantQualifierName") // Cannot use imports here. val resolution = io.spine.gradle.internal.DependencyResolution - @Suppress("RemoveRedundantQualifierName") - val deps = io.spine.gradle.internal.Deps resolution.defaultRepositories(repositories) resolution.forceConfiguration(configurations) } @@ -150,13 +149,11 @@ subprojects { } protobuf { - protobuf.generatedFilesBaseDir = generatedRootDir + generatedFilesBaseDir = generatedRootDir - protobuf.protoc(object : groovy.lang.Closure(this) { - private fun doCall(locator: com.google.protobuf.gradle.ExecutableLocator) { - locator.artifact = Deps.build.protoc - } - }) + protoc { + artifact = Deps.build.protoc + } } tasks.test.configure { diff --git a/buildSrc/build.gradle.kts b/buildSrc/build.gradle.kts index bdfd32a6d6..7dc929afca 100644 --- a/buildSrc/build.gradle.kts +++ b/buildSrc/build.gradle.kts @@ -19,6 +19,8 @@ */ plugins { + // Use Kotlin for `buildSrc`. + // https://kotlinlang.org/docs/reference/using-gradle.html#targeting-the-jvm kotlin("jvm").version("1.3.72") } @@ -26,3 +28,9 @@ repositories { mavenLocal() jcenter() } + +val jacksonVersion = "2.11.0" + +dependencies { + implementation("com.fasterxml.jackson.dataformat:jackson-dataformat-xml:$jacksonVersion") +} diff --git a/buildSrc/src/main/kotlin/io/spine/gradle/internal/CheckVersionIncrement.kt b/buildSrc/src/main/kotlin/io/spine/gradle/internal/CheckVersionIncrement.kt new file mode 100644 index 0000000000..60709874e8 --- /dev/null +++ b/buildSrc/src/main/kotlin/io/spine/gradle/internal/CheckVersionIncrement.kt @@ -0,0 +1,104 @@ +/* + * Copyright 2020, TeamDev. All rights reserved. + * + * Redistribution and use in source and/or binary forms, with or without + * modification, must retain the above copyright notice and the following + * disclaimer. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package io.spine.gradle.internal + +import com.fasterxml.jackson.databind.DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES +import com.fasterxml.jackson.dataformat.xml.XmlMapper +import org.gradle.api.GradleException +import org.gradle.api.Project +import org.gradle.api.internal.AbstractTask +import org.gradle.api.tasks.Input +import org.gradle.api.tasks.TaskAction +import java.net.URL + +/** + * A task which verifies that the current version of the library has not been published to the given + * Maven repository yet. + */ +open class CheckVersionIncrement : AbstractTask() { + + /** + * The Maven repository in which to look for published artifacts. + * + * We only check the `releases` repository. Artifacts in `snapshots` repository still may be + * overridden. + */ + @Input + lateinit var repository: Repository + + @Input + private val version: String = project.version as String + + @TaskAction + private fun fetchAndCheck() { + val artifact = "${project.artifactPath()}/${MavenMetadata.FILE_NAME}" + val repoUrl = repository.releases + val metadata = fetch(repoUrl, artifact) + val versions = metadata.versioning.versions + val versionExists = versions.contains(version) + if (versionExists) { + throw GradleException(""" + Version `$version` is already published to maven repository `$repoUrl`. + Try incrementing the library version. + All available versions are: ${versions.joinToString(separator = ", ")}. + + To disable this check, run Gradle with `-x $name`. + """.trimIndent() + ) + } + } + + private fun fetch(repository: String, artifact: String): MavenMetadata { + val url = URL("$repository/$artifact") + return MavenMetadata.fetchAndParse(url) + } + + private fun Project.artifactPath(): String { + val group = this.group as String + val name = "spine-${this.name}" + + val pathElements = ArrayList(group.split('.')) + pathElements.add(name) + val path = pathElements.joinToString(separator = "/") + return path + } +} + +private data class MavenMetadata(var versioning: Versioning = Versioning()) { + + companion object { + + const val FILE_NAME = "maven-metadata.xml" + + private val mapper = XmlMapper() + + init { + mapper.configure(FAIL_ON_UNKNOWN_PROPERTIES, false) + } + + fun fetchAndParse(url: URL): MavenMetadata { + val metadata = mapper.readValue(url, MavenMetadata::class.java) + return metadata + } + } +} + +private data class Versioning(var versions: List = listOf()) diff --git a/buildSrc/src/main/kotlin/io/spine/gradle/internal/IncrementGuard.kt b/buildSrc/src/main/kotlin/io/spine/gradle/internal/IncrementGuard.kt new file mode 100644 index 0000000000..c227f49889 --- /dev/null +++ b/buildSrc/src/main/kotlin/io/spine/gradle/internal/IncrementGuard.kt @@ -0,0 +1,46 @@ +/* + * Copyright 2020, TeamDev. All rights reserved. + * + * Redistribution and use in source and/or binary forms, with or without + * modification, must retain the above copyright notice and the following + * disclaimer. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package io.spine.gradle.internal + +import org.gradle.api.Plugin +import org.gradle.api.Project + +/** + * Gradle plugin which adds a [CheckVersionIncrement] task. + * + * The task is called `checkVersionIncrement` inserted before the `check` task. + */ +class IncrementGuard : Plugin { + + companion object { + const val taskName = "checkVersionIncrement" + } + + override fun apply(target: Project) { + val tasks = target.tasks + tasks.register(taskName, CheckVersionIncrement::class.java) { + it.repository = PublishingRepos.cloudRepo + tasks.getByName("check").dependsOn(it) + + it.shouldRunAfter("test") + } + } +} diff --git a/config b/config index 5ffcb1a8db..d9223f98f5 160000 --- a/config +++ b/config @@ -1 +1 @@ -Subproject commit 5ffcb1a8dbe4b9f14aacb9ecf663c5e639eac4b5 +Subproject commit d9223f98f58cca6a6c91d3339f0fa6c366e3a00c diff --git a/license-report.md b/license-report.md index cac8d088b0..8720bb716e 100644 --- a/license-report.md +++ b/license-report.md @@ -1,6 +1,6 @@ -# Dependencies of `io.spine:spine-base:1.5.11` +# Dependencies of `io.spine:spine-base:1.5.12` ## Runtime 1. **Group:** com.google.code.findbugs **Name:** jsr305 **Version:** 3.0.2 @@ -328,12 +328,12 @@ The dependencies distributed under several licenses, are used according their commercial-use-friendly license. -This report was generated on **Mon May 18 17:02:11 EEST 2020** using [Gradle-License-Report plugin](https://github.com/jk1/Gradle-License-Report) by Evgeny Naumenko, licensed under [Apache 2.0 License](https://github.com/jk1/Gradle-License-Report/blob/master/LICENSE). +This report was generated on **Tue May 26 19:54:52 EEST 2020** using [Gradle-License-Report plugin](https://github.com/jk1/Gradle-License-Report) by Evgeny Naumenko, licensed under [Apache 2.0 License](https://github.com/jk1/Gradle-License-Report/blob/master/LICENSE). -# Dependencies of `io.spine.tools:spine-errorprone-checks:1.5.11` +# Dependencies of `io.spine.tools:spine-errorprone-checks:1.5.12` ## Runtime 1. **Group:** com.github.ben-manes.caffeine **Name:** caffeine **Version:** 2.7.0 @@ -773,12 +773,12 @@ This report was generated on **Mon May 18 17:02:11 EEST 2020** using [Gradle-Lic The dependencies distributed under several licenses, are used according their commercial-use-friendly license. -This report was generated on **Mon May 18 17:02:16 EEST 2020** using [Gradle-License-Report plugin](https://github.com/jk1/Gradle-License-Report) by Evgeny Naumenko, licensed under [Apache 2.0 License](https://github.com/jk1/Gradle-License-Report/blob/master/LICENSE). +This report was generated on **Tue May 26 19:54:53 EEST 2020** using [Gradle-License-Report plugin](https://github.com/jk1/Gradle-License-Report) by Evgeny Naumenko, licensed under [Apache 2.0 License](https://github.com/jk1/Gradle-License-Report/blob/master/LICENSE). -# Dependencies of `io.spine.tools:spine-javadoc-filter:1.5.11` +# Dependencies of `io.spine.tools:spine-javadoc-filter:1.5.12` ## Runtime 1. **Group:** com.google.android **Name:** annotations **Version:** 4.1.1.4 @@ -1156,12 +1156,12 @@ This report was generated on **Mon May 18 17:02:16 EEST 2020** using [Gradle-Lic The dependencies distributed under several licenses, are used according their commercial-use-friendly license. -This report was generated on **Mon May 18 17:02:19 EEST 2020** using [Gradle-License-Report plugin](https://github.com/jk1/Gradle-License-Report) by Evgeny Naumenko, licensed under [Apache 2.0 License](https://github.com/jk1/Gradle-License-Report/blob/master/LICENSE). +This report was generated on **Tue May 26 19:54:54 EEST 2020** using [Gradle-License-Report plugin](https://github.com/jk1/Gradle-License-Report) by Evgeny Naumenko, licensed under [Apache 2.0 License](https://github.com/jk1/Gradle-License-Report/blob/master/LICENSE). -# Dependencies of `io.spine.tools:spine-javadoc-prettifier:1.5.11` +# Dependencies of `io.spine.tools:spine-javadoc-prettifier:1.5.12` ## Runtime 1. **Group:** com.google.code.findbugs **Name:** jsr305 **Version:** 3.0.2 @@ -1521,12 +1521,12 @@ This report was generated on **Mon May 18 17:02:19 EEST 2020** using [Gradle-Lic The dependencies distributed under several licenses, are used according their commercial-use-friendly license. -This report was generated on **Mon May 18 17:02:23 EEST 2020** using [Gradle-License-Report plugin](https://github.com/jk1/Gradle-License-Report) by Evgeny Naumenko, licensed under [Apache 2.0 License](https://github.com/jk1/Gradle-License-Report/blob/master/LICENSE). +This report was generated on **Tue May 26 19:54:54 EEST 2020** using [Gradle-License-Report plugin](https://github.com/jk1/Gradle-License-Report) by Evgeny Naumenko, licensed under [Apache 2.0 License](https://github.com/jk1/Gradle-License-Report/blob/master/LICENSE). -# Dependencies of `io.spine.tools:spine-model-compiler:1.5.11` +# Dependencies of `io.spine.tools:spine-model-compiler:1.5.12` ## Runtime 1. **Group:** com.google.code.findbugs **Name:** jsr305 **Version:** 3.0.2 @@ -1902,12 +1902,12 @@ This report was generated on **Mon May 18 17:02:23 EEST 2020** using [Gradle-Lic The dependencies distributed under several licenses, are used according their commercial-use-friendly license. -This report was generated on **Mon May 18 17:02:35 EEST 2020** using [Gradle-License-Report plugin](https://github.com/jk1/Gradle-License-Report) by Evgeny Naumenko, licensed under [Apache 2.0 License](https://github.com/jk1/Gradle-License-Report/blob/master/LICENSE). +This report was generated on **Tue May 26 19:54:55 EEST 2020** using [Gradle-License-Report plugin](https://github.com/jk1/Gradle-License-Report) by Evgeny Naumenko, licensed under [Apache 2.0 License](https://github.com/jk1/Gradle-License-Report/blob/master/LICENSE). -# Dependencies of `io.spine.tools:spine-mute-logging:1.5.11` +# Dependencies of `io.spine.tools:spine-mute-logging:1.5.12` ## Runtime 1. **Group:** com.google.auto.value **Name:** auto-value-annotations **Version:** 1.6.3 @@ -2281,12 +2281,12 @@ This report was generated on **Mon May 18 17:02:35 EEST 2020** using [Gradle-Lic The dependencies distributed under several licenses, are used according their commercial-use-friendly license. -This report was generated on **Mon May 18 17:02:38 EEST 2020** using [Gradle-License-Report plugin](https://github.com/jk1/Gradle-License-Report) by Evgeny Naumenko, licensed under [Apache 2.0 License](https://github.com/jk1/Gradle-License-Report/blob/master/LICENSE). +This report was generated on **Tue May 26 19:54:55 EEST 2020** using [Gradle-License-Report plugin](https://github.com/jk1/Gradle-License-Report) by Evgeny Naumenko, licensed under [Apache 2.0 License](https://github.com/jk1/Gradle-License-Report/blob/master/LICENSE). -# Dependencies of `io.spine.tools:spine-plugin-base:1.5.11` +# Dependencies of `io.spine.tools:spine-plugin-base:1.5.12` ## Runtime 1. **Group:** com.google.code.findbugs **Name:** jsr305 **Version:** 3.0.2 @@ -2646,12 +2646,12 @@ This report was generated on **Mon May 18 17:02:38 EEST 2020** using [Gradle-Lic The dependencies distributed under several licenses, are used according their commercial-use-friendly license. -This report was generated on **Mon May 18 17:02:43 EEST 2020** using [Gradle-License-Report plugin](https://github.com/jk1/Gradle-License-Report) by Evgeny Naumenko, licensed under [Apache 2.0 License](https://github.com/jk1/Gradle-License-Report/blob/master/LICENSE). +This report was generated on **Tue May 26 19:54:56 EEST 2020** using [Gradle-License-Report plugin](https://github.com/jk1/Gradle-License-Report) by Evgeny Naumenko, licensed under [Apache 2.0 License](https://github.com/jk1/Gradle-License-Report/blob/master/LICENSE). -# Dependencies of `io.spine.tools:spine-plugin-testlib:1.5.11` +# Dependencies of `io.spine.tools:spine-plugin-testlib:1.5.12` ## Runtime 1. **Group:** com.google.auto.value **Name:** auto-value-annotations **Version:** 1.6.3 @@ -3065,12 +3065,12 @@ This report was generated on **Mon May 18 17:02:43 EEST 2020** using [Gradle-Lic The dependencies distributed under several licenses, are used according their commercial-use-friendly license. -This report was generated on **Mon May 18 17:02:49 EEST 2020** using [Gradle-License-Report plugin](https://github.com/jk1/Gradle-License-Report) by Evgeny Naumenko, licensed under [Apache 2.0 License](https://github.com/jk1/Gradle-License-Report/blob/master/LICENSE). +This report was generated on **Tue May 26 19:54:56 EEST 2020** using [Gradle-License-Report plugin](https://github.com/jk1/Gradle-License-Report) by Evgeny Naumenko, licensed under [Apache 2.0 License](https://github.com/jk1/Gradle-License-Report/blob/master/LICENSE). -# Dependencies of `io.spine.tools:spine-proto-dart-plugin:1.5.11` +# Dependencies of `io.spine.tools:spine-proto-dart-plugin:1.5.12` ## Runtime 1. **Group:** com.google.code.findbugs **Name:** jsr305 **Version:** 3.0.2 @@ -3430,12 +3430,12 @@ This report was generated on **Mon May 18 17:02:49 EEST 2020** using [Gradle-Lic The dependencies distributed under several licenses, are used according their commercial-use-friendly license. -This report was generated on **Mon May 18 17:02:54 EEST 2020** using [Gradle-License-Report plugin](https://github.com/jk1/Gradle-License-Report) by Evgeny Naumenko, licensed under [Apache 2.0 License](https://github.com/jk1/Gradle-License-Report/blob/master/LICENSE). +This report was generated on **Tue May 26 19:54:56 EEST 2020** using [Gradle-License-Report plugin](https://github.com/jk1/Gradle-License-Report) by Evgeny Naumenko, licensed under [Apache 2.0 License](https://github.com/jk1/Gradle-License-Report/blob/master/LICENSE). -# Dependencies of `io.spine.tools:spine-proto-js-plugin:1.5.11` +# Dependencies of `io.spine.tools:spine-proto-js-plugin:1.5.12` ## Runtime 1. **Group:** com.google.code.findbugs **Name:** jsr305 **Version:** 3.0.2 @@ -3795,12 +3795,12 @@ This report was generated on **Mon May 18 17:02:54 EEST 2020** using [Gradle-Lic The dependencies distributed under several licenses, are used according their commercial-use-friendly license. -This report was generated on **Mon May 18 17:03:04 EEST 2020** using [Gradle-License-Report plugin](https://github.com/jk1/Gradle-License-Report) by Evgeny Naumenko, licensed under [Apache 2.0 License](https://github.com/jk1/Gradle-License-Report/blob/master/LICENSE). +This report was generated on **Tue May 26 19:54:57 EEST 2020** using [Gradle-License-Report plugin](https://github.com/jk1/Gradle-License-Report) by Evgeny Naumenko, licensed under [Apache 2.0 License](https://github.com/jk1/Gradle-License-Report/blob/master/LICENSE). -# Dependencies of `io.spine.tools:spine-protoc-api:1.5.11` +# Dependencies of `io.spine.tools:spine-protoc-api:1.5.12` ## Runtime 1. **Group:** com.google.code.findbugs **Name:** jsr305 **Version:** 3.0.2 @@ -4120,12 +4120,12 @@ This report was generated on **Mon May 18 17:03:04 EEST 2020** using [Gradle-Lic The dependencies distributed under several licenses, are used according their commercial-use-friendly license. -This report was generated on **Mon May 18 17:03:09 EEST 2020** using [Gradle-License-Report plugin](https://github.com/jk1/Gradle-License-Report) by Evgeny Naumenko, licensed under [Apache 2.0 License](https://github.com/jk1/Gradle-License-Report/blob/master/LICENSE). +This report was generated on **Tue May 26 19:54:57 EEST 2020** using [Gradle-License-Report plugin](https://github.com/jk1/Gradle-License-Report) by Evgeny Naumenko, licensed under [Apache 2.0 License](https://github.com/jk1/Gradle-License-Report/blob/master/LICENSE). -# Dependencies of `io.spine.tools:spine-protoc-plugin:1.5.11` +# Dependencies of `io.spine.tools:spine-protoc-plugin:1.5.12` ## Runtime 1. **Group:** com.google.code.findbugs **Name:** jsr305 **Version:** 3.0.2 @@ -4453,12 +4453,12 @@ This report was generated on **Mon May 18 17:03:09 EEST 2020** using [Gradle-Lic The dependencies distributed under several licenses, are used according their commercial-use-friendly license. -This report was generated on **Mon May 18 17:03:09 EEST 2020** using [Gradle-License-Report plugin](https://github.com/jk1/Gradle-License-Report) by Evgeny Naumenko, licensed under [Apache 2.0 License](https://github.com/jk1/Gradle-License-Report/blob/master/LICENSE). +This report was generated on **Tue May 26 19:54:58 EEST 2020** using [Gradle-License-Report plugin](https://github.com/jk1/Gradle-License-Report) by Evgeny Naumenko, licensed under [Apache 2.0 License](https://github.com/jk1/Gradle-License-Report/blob/master/LICENSE). -# Dependencies of `io.spine:spine-testlib:1.5.11` +# Dependencies of `io.spine:spine-testlib:1.5.12` ## Runtime 1. **Group:** com.google.auto.value **Name:** auto-value-annotations **Version:** 1.6.3 @@ -4832,12 +4832,12 @@ This report was generated on **Mon May 18 17:03:09 EEST 2020** using [Gradle-Lic The dependencies distributed under several licenses, are used according their commercial-use-friendly license. -This report was generated on **Mon May 18 17:03:13 EEST 2020** using [Gradle-License-Report plugin](https://github.com/jk1/Gradle-License-Report) by Evgeny Naumenko, licensed under [Apache 2.0 License](https://github.com/jk1/Gradle-License-Report/blob/master/LICENSE). +This report was generated on **Tue May 26 19:54:58 EEST 2020** using [Gradle-License-Report plugin](https://github.com/jk1/Gradle-License-Report) by Evgeny Naumenko, licensed under [Apache 2.0 License](https://github.com/jk1/Gradle-License-Report/blob/master/LICENSE). -# Dependencies of `io.spine.tools:spine-tool-base:1.5.11` +# Dependencies of `io.spine.tools:spine-tool-base:1.5.12` ## Runtime 1. **Group:** com.google.code.findbugs **Name:** jsr305 **Version:** 3.0.2 @@ -5165,12 +5165,12 @@ This report was generated on **Mon May 18 17:03:13 EEST 2020** using [Gradle-Lic The dependencies distributed under several licenses, are used according their commercial-use-friendly license. -This report was generated on **Mon May 18 17:03:17 EEST 2020** using [Gradle-License-Report plugin](https://github.com/jk1/Gradle-License-Report) by Evgeny Naumenko, licensed under [Apache 2.0 License](https://github.com/jk1/Gradle-License-Report/blob/master/LICENSE). +This report was generated on **Tue May 26 19:54:58 EEST 2020** using [Gradle-License-Report plugin](https://github.com/jk1/Gradle-License-Report) by Evgeny Naumenko, licensed under [Apache 2.0 License](https://github.com/jk1/Gradle-License-Report/blob/master/LICENSE). -# Dependencies of `io.spine.tools:spine-validation-generator:1.5.11` +# Dependencies of `io.spine.tools:spine-validation-generator:1.5.12` ## Runtime 1. **Group:** com.google.code.findbugs **Name:** jsr305 **Version:** 3.0.2 @@ -5498,4 +5498,4 @@ This report was generated on **Mon May 18 17:03:17 EEST 2020** using [Gradle-Lic The dependencies distributed under several licenses, are used according their commercial-use-friendly license. -This report was generated on **Mon May 18 17:03:21 EEST 2020** using [Gradle-License-Report plugin](https://github.com/jk1/Gradle-License-Report) by Evgeny Naumenko, licensed under [Apache 2.0 License](https://github.com/jk1/Gradle-License-Report/blob/master/LICENSE). \ No newline at end of file +This report was generated on **Tue May 26 19:54:59 EEST 2020** using [Gradle-License-Report plugin](https://github.com/jk1/Gradle-License-Report) by Evgeny Naumenko, licensed under [Apache 2.0 License](https://github.com/jk1/Gradle-License-Report/blob/master/LICENSE). \ No newline at end of file diff --git a/pom.xml b/pom.xml index f2dd9278fa..f780e4d77d 100644 --- a/pom.xml +++ b/pom.xml @@ -12,7 +12,7 @@ all modules and does not describe the project structure per-subproject. io.spine spine-base -1.5.11 +1.5.12 2015 @@ -154,7 +154,7 @@ all modules and does not describe the project structure per-subproject. io.spine.tools spine-protoc-plugin - 1.5.11 + 1.5.12 test diff --git a/pull b/pull new file mode 100755 index 0000000000..cafe48cb16 --- /dev/null +++ b/pull @@ -0,0 +1,29 @@ +#!/usr/bin/env bash + +# +# Copyright 2020, TeamDev. All rights reserved. +# +# Redistribution and use in source and/or binary forms, with or without +# modification, must retain the above copyright notice and the following +# disclaimer. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# + +./config/pull + +echo "Copying buildSrc to base-validating-builders" +cp -R ./buildSrc ./base-validating-builders + +echo "Copying buildSrc to smoke-tests" +cp -R ./buildSrc ./tools/smoke-tests diff --git a/pull.bat b/pull.bat new file mode 100644 index 0000000000..50f0ef31aa --- /dev/null +++ b/pull.bat @@ -0,0 +1,29 @@ +@echo off + +rem +rem Copyright 2020, TeamDev. All rights reserved. +rem +rem Redistribution and use in source and/or binary forms, with or without +rem modification, must retain the above copyright notice and the following +rem disclaimer. +rem +rem THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +rem "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +rem LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +rem A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +rem OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +rem SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +rem LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +rem DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +rem THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +rem (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +rem OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +rem + +.\config\pull.bat + +echo "Copying buildSrc to base-validating-builders" +xcopy /S/E/I/F/Y .\buildSrc ..\base-validating-builders\buildSrc + +echo "Copying buildSrc to smoke-tests" +xcopy /S/E/I/F/Y .\buildSrc ..\tools\smoke-tests\buildSrc diff --git a/script/same-dir.sh b/script/same-dir.sh new file mode 100755 index 0000000000..b3fffb4120 --- /dev/null +++ b/script/same-dir.sh @@ -0,0 +1,32 @@ +#!/usr/bin/env bash + +# +# Copyright 2020, TeamDev. All rights reserved. +# +# Redistribution and use in source and/or binary forms, with or without +# modification, must retain the above copyright notice and the following +# disclaimer. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# + +difference=$(diff -r "$1" "$2") + +if [ -z "$difference" ]; +then + echo "Directories $1 and $2 are equal." +else + echo "Directories $1 and $2 are NOT equal." + echo "$difference" + exit 1 +fi diff --git a/tools/javadoc-prettifier/src/test/java/io/spine/tools/protodoc/ProtoJavadocPluginTest.java b/tools/javadoc-prettifier/src/test/java/io/spine/tools/protodoc/ProtoJavadocPluginTest.java index ae518cfc41..fcc2a93672 100644 --- a/tools/javadoc-prettifier/src/test/java/io/spine/tools/protodoc/ProtoJavadocPluginTest.java +++ b/tools/javadoc-prettifier/src/test/java/io/spine/tools/protodoc/ProtoJavadocPluginTest.java @@ -70,14 +70,14 @@ void setUp(@TempDir Path tempDirPath) { @Test @DisplayName("apply to project") - void apply_to_project() { + void applyToProject() { PluginContainer plugins = project.getPlugins(); assertTrue(plugins.hasPlugin(PLUGIN_ID)); } @Test @DisplayName("have extension") - void have_extension() { + void haveExtension() { Extension extension = project.getExtensions() .getByType(Extension.class); assertNotNull(extension); @@ -85,7 +85,7 @@ void have_extension() { @Test @DisplayName("add formatProtoDoc task") - void add_task_formatProtoDoc() { + void addTaskFormatProtoDoc() { Task task = task(formatProtoDoc); assertNotNull(task); assertTrue(dependsOn(task, generateProto)); @@ -94,7 +94,7 @@ void add_task_formatProtoDoc() { @Test @DisplayName("add formatTestProtoDoc task") - void add_task_formatTestProtoDoc() { + void addTaskFormatTestProtoDoc() { Task task = task(formatTestProtoDoc); assertNotNull(task); assertTrue(dependsOn(task, generateTestProto)); @@ -103,7 +103,7 @@ void add_task_formatTestProtoDoc() { @Test @DisplayName("format generated java sources") - void format_generated_java_sources() throws IOException { + void formatGeneratedJavaSources() throws IOException { String text = "javadoc text"; String generatedFieldDescription = " field description"; String textInPreTags = new StringBuilder().append(OPENING_PRE) @@ -118,7 +118,7 @@ void format_generated_java_sources() throws IOException { @Test @DisplayName("handle multiline code snippets") - void handle_multiline_code_snippets_properly() throws IOException { + void handleMultilineCodeSnippetsProperly() throws IOException { String protoDoc = multilineJavadoc(BACKTICK, BACKTICK); String javadoc = multilineJavadoc("{@code ", "}"); diff --git a/tools/javadoc-prettifier/src/test/resources/build.gradle b/tools/javadoc-prettifier/src/test/resources/build.gradle.kts similarity index 69% rename from tools/javadoc-prettifier/src/test/resources/build.gradle rename to tools/javadoc-prettifier/src/test/resources/build.gradle.kts index 0622af5297..6db06a9ab7 100644 --- a/tools/javadoc-prettifier/src/test/resources/build.gradle +++ b/tools/javadoc-prettifier/src/test/resources/build.gradle.kts @@ -21,26 +21,25 @@ buildscript { // NOTE: this file is copied from the root project in the test setup. - apply from: "$rootDir/test-env.gradle" - - apply from: "$enclosingRootDir/config/gradle/dependencies.gradle" - apply from: "$enclosingRootDir/version.gradle.kts" + apply(from = "$rootDir/test-env.gradle") + apply(from = "${extra["enclosingRootDir"]}/version.gradle.kts") repositories { mavenLocal() jcenter() } + val spineVersion: String by extra dependencies { - classpath "io.spine.tools:spine-javadoc-prettifier:$spineVersion" - classpath deps.build.gradlePlugins.protobuf + classpath("io.spine.tools:spine-javadoc-prettifier:$spineVersion") + classpath(io.spine.gradle.internal.Deps.build.gradlePlugins.protobuf) } } -apply plugin: 'java' -apply plugin: 'io.spine.tools.protobuf-javadoc-plugin' -apply plugin: 'com.google.protobuf' +apply(plugin = "java") +apply(plugin = "com.google.protobuf") +apply(plugin = "io.spine.tools.protobuf-javadoc-plugin") -protoJavadoc { - mainGenProtoDir = "generated/main/java" +extensions["protoJavadoc"].withGroovyBuilder { + setProperty("mainGenProtoDir", "generated/main/java") } diff --git a/tools/model-compiler/build.gradle.kts b/tools/model-compiler/build.gradle.kts index 15a893b713..b71f3ed79f 100644 --- a/tools/model-compiler/build.gradle.kts +++ b/tools/model-compiler/build.gradle.kts @@ -18,8 +18,7 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -import com.google.protobuf.gradle.ProtobufConfigurator.JavaGenerateProtoTaskCollection -import groovy.lang.Closure +import com.google.protobuf.gradle.* import groovy.lang.GString import io.spine.gradle.internal.Deps import java.nio.file.Files @@ -54,19 +53,15 @@ dependencies { } protobuf { - protobuf.generateProtoTasks( - object : Closure(this) { - private fun doCall(tasks: JavaGenerateProtoTaskCollection) { - tasks.all().forEach { task -> - val scope = task.sourceSet.name - task.generateDescriptorSet = true - task.descriptorSetOptions.path = GString.EMPTY.plus("$buildDir/descriptors/${scope}/io.spine.tools.spine-model-compiler-${scope}.desc") - task.descriptorSetOptions.includeImports = true - task.descriptorSetOptions.includeSourceInfo = true - } - } - } - ) + generateProtoTasks { + all().forEach { task -> + val scope = task.sourceSet.name + task.generateDescriptorSet = true + task.descriptorSetOptions.path = GString.EMPTY.plus("$buildDir/descriptors/${scope}/io.spine.tools.spine-model-compiler-${scope}.desc") + task.descriptorSetOptions.includeImports = true + task.descriptorSetOptions.includeSourceInfo = true + } + } } sourceSets { diff --git a/tools/model-compiler/src/test/resources/build.gradle b/tools/model-compiler/src/test/resources/build.gradle.kts similarity index 54% rename from tools/model-compiler/src/test/resources/build.gradle rename to tools/model-compiler/src/test/resources/build.gradle.kts index 977e4c973c..c51323939f 100644 --- a/tools/model-compiler/src/test/resources/build.gradle +++ b/tools/model-compiler/src/test/resources/build.gradle.kts @@ -18,66 +18,68 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +import io.spine.gradle.internal.Repos +import org.gradle.api.file.SourceDirectorySet +import java.net.URI + // Common build file for the tests with same configuration buildscript { // NOTE: this file is copied from the root project in the test setup. - apply from: "$rootDir/test-env.gradle" - - apply from: "$enclosingRootDir/config/gradle/dependencies.gradle" - apply from: "$enclosingRootDir/version.gradle.kts" + apply(from = "$rootDir/test-env.gradle") + apply(from = "${extra["enclosingRootDir"]}/version.gradle.kts") repositories { mavenLocal() jcenter() - maven { url = repos.spine } - maven { url = repos.spineSnapshots } + maven { url = java.net.URI(io.spine.gradle.internal.Repos.spine) } } + val spineVersion: String by extra dependencies { - classpath deps.build.protobuf + io.spine.gradle.internal.Deps.build.protobuf.forEach { classpath(it) } // Exclude `guava:18.0` as a transitive dependency by Protobuf Gradle plugin. - classpath (deps.build.gradlePlugins.protobuf) { - exclude group: 'com.google.guava' + classpath(io.spine.gradle.internal.Deps.build.gradlePlugins.protobuf) { + exclude(group = "com.google.guava") } - classpath "io.spine.tools:spine-model-compiler:${spineVersion}" + classpath("io.spine.tools:spine-model-compiler:${spineVersion}") } +} - configurations.all({ - resolutionStrategy.cacheChangingModulesFor(0, 'seconds') - }) +plugins { + java } // NOTE: this file is copied from the root project in the test setup. -apply from: "$rootDir/test-env.gradle" - -apply plugin: 'java' -apply plugin: 'com.google.protobuf' -apply plugin: 'io.spine.tools.spine-model-compiler' -apply from: "$enclosingRootDir/config/gradle/model-compiler.gradle" +apply { + plugin("com.google.protobuf") + plugin("io.spine.tools.spine-model-compiler") + from("$rootDir/test-env.gradle") + from("${extra["enclosingRootDir"]}/config/gradle/model-compiler.gradle") +} -group = 'io.spine.test' -version = '3.14' +group = "io.spine.test" +version = "3.14" repositories { mavenLocal() jcenter() - maven { url = repos.spine } - maven { url = repos.spineSnapshots } + maven { url = URI(Repos.spine) } } +val spineVersion: String by extra dependencies { - implementation "io.spine:spine-base:$spineVersion" + implementation("io.spine:spine-base:$spineVersion") } sourceSets { main { - proto.srcDirs "$projectDir/src/main/proto" - java.srcDirs "$projectDir/generated/main/java", "$projectDir/generated/main/spine" - resources.srcDirs "$projectDir/generated/main/resources" + java.srcDirs("$projectDir/generated/main/java", "$projectDir/generated/main/spine") + resources.srcDir("$projectDir/generated/main/resources") + (extensions.getByName("proto") as SourceDirectorySet).srcDir("$projectDir/src/main/proto") } } diff --git a/tools/plugin-base/build.gradle.kts b/tools/plugin-base/build.gradle.kts index a7d89c0f41..349314f866 100644 --- a/tools/plugin-base/build.gradle.kts +++ b/tools/plugin-base/build.gradle.kts @@ -19,8 +19,7 @@ */ import com.google.common.io.Files -import com.google.protobuf.gradle.ProtobufConfigurator.JavaGenerateProtoTaskCollection -import groovy.lang.Closure +import com.google.protobuf.gradle.* import groovy.lang.GString import io.spine.gradle.internal.Deps import java.util.* @@ -38,14 +37,12 @@ dependencies { } protobuf { - protobuf.generateProtoTasks(object : Closure(this) { - private fun doCall(tasks: JavaGenerateProtoTaskCollection) { - for (task in tasks.all()) { - task.generateDescriptorSet = true - task.descriptorSetOptions.path = GString.EMPTY.plus("$buildDir/descriptors/${task.sourceSet.name}/known_types.desc") - } + generateProtoTasks { + for (task in all()) { + task.generateDescriptorSet = true + task.descriptorSetOptions.path = GString.EMPTY.plus("$buildDir/descriptors/${task.sourceSet.name}/known_types.desc") } - }) + } } val spineBaseVersion: String by extra diff --git a/tools/plugin-testlib/src/main/java/io/spine/tools/gradle/testing/BuildGradle.java b/tools/plugin-testlib/src/main/java/io/spine/tools/gradle/testing/BuildGradle.java index 0cb3a2ce98..df28dde87f 100644 --- a/tools/plugin-testlib/src/main/java/io/spine/tools/gradle/testing/BuildGradle.java +++ b/tools/plugin-testlib/src/main/java/io/spine/tools/gradle/testing/BuildGradle.java @@ -21,6 +21,7 @@ package io.spine.tools.gradle.testing; import com.google.common.annotations.VisibleForTesting; +import io.spine.io.Resource; import java.io.IOException; import java.io.InputStream; @@ -30,7 +31,11 @@ import static com.google.common.base.Preconditions.checkNotNull; /** - * Creates {@link #FILE_NAME} file in the root of the test project, copying it from resources. + * Creates {@link #BUILD_GRADLE build.gradle} or {@link #BUILD_GRADLE_KTS build.gradle.kts} file in + * the root of the test project, copying it from resources. + * + *

If a {@code build.gradle} file is found, it is used for the build. Otherwise, if + * a {@code build.gradle.kts} file is found, it is used for the build. */ final class BuildGradle { @@ -38,7 +43,8 @@ final class BuildGradle { * The name of the build file. */ @VisibleForTesting - static final String FILE_NAME = "build.gradle"; + static final String BUILD_GRADLE = "build.gradle"; + private static final String BUILD_GRADLE_KTS = "build.gradle.kts"; private final Path testProjectRoot; @@ -46,11 +52,28 @@ final class BuildGradle { testProjectRoot = root; } + /** + * Copies a Gradle build script from the classpath into the test project directory. + * + * @throws IOException + * if the file cannot be written + */ void createFile() throws IOException { - Path resultingPath = testProjectRoot.resolve(FILE_NAME); + Resource buildGradle = Resource.file(BUILD_GRADLE); + Resource buildGradleKts = Resource.file(BUILD_GRADLE_KTS); + Path resultingPath; + Resource file; + if (buildGradle.exists()) { + resultingPath = testProjectRoot.resolve(BUILD_GRADLE); + file = buildGradle; + } else if (buildGradleKts.exists()) { + resultingPath = testProjectRoot.resolve(BUILD_GRADLE_KTS); + file = buildGradleKts; + } else { + throw new IllegalStateException("Build script is not found."); + } - try (InputStream fileContent = getClass().getClassLoader() - .getResourceAsStream(FILE_NAME)) { + try (InputStream fileContent = file.open()) { Files.createDirectories(resultingPath.getParent()); checkNotNull(fileContent); Files.copy(fileContent, resultingPath); diff --git a/tools/plugin-testlib/src/main/java/io/spine/tools/gradle/testing/GradleProject.java b/tools/plugin-testlib/src/main/java/io/spine/tools/gradle/testing/GradleProject.java index 608257b96f..cf6f90fbda 100644 --- a/tools/plugin-testlib/src/main/java/io/spine/tools/gradle/testing/GradleProject.java +++ b/tools/plugin-testlib/src/main/java/io/spine/tools/gradle/testing/GradleProject.java @@ -39,6 +39,7 @@ import static com.google.common.base.Strings.isNullOrEmpty; import static com.google.common.base.Throwables.getRootCause; import static com.google.common.collect.Lists.newLinkedList; +import static io.spine.io.Files2.copyDir; import static java.util.Arrays.asList; /** @@ -51,6 +52,7 @@ public final class GradleProject { private static final String BASE_PROTO_LOCATION = "src/main/proto/"; private static final String BASE_JAVA_LOCATION = "src/main/java/"; private static final String JAVA_PLUGIN_NAME = "java"; + private static final String BUILD_SRC = "buildSrc"; private final String name; private final GradleRunner gradleRunner; @@ -80,6 +82,7 @@ private GradleProject(Builder builder) throws IOException { gradleRunner.withPluginClasspath(); } writeGradleScripts(); + writeBuildSrc(); writeProtoFiles(builder.protoFileNames); writeJavaFiles(builder.javaFileNames); } @@ -94,6 +97,14 @@ private void writeGradleScripts() throws IOException { testEnvGradle.createFile(); } + private void writeBuildSrc() throws IOException { + Path projectRoot = ProjectRoot.instance() + .toPath(); + Path buildSrc = projectRoot.resolve(BUILD_SRC); + Path target = testProjectRoot(); + copyDir(buildSrc, target); + } + private void writeProtoFiles(Iterable fileNames) throws IOException { for (String protoFile : fileNames) { writeProto(protoFile); diff --git a/tools/plugin-testlib/src/main/java/io/spine/tools/gradle/testing/ProjectRoot.java b/tools/plugin-testlib/src/main/java/io/spine/tools/gradle/testing/ProjectRoot.java index 2126da6c60..b5ebdc8f13 100644 --- a/tools/plugin-testlib/src/main/java/io/spine/tools/gradle/testing/ProjectRoot.java +++ b/tools/plugin-testlib/src/main/java/io/spine/tools/gradle/testing/ProjectRoot.java @@ -28,18 +28,19 @@ import static java.nio.file.Files.exists; /** - * Finds a root of a project by presence of the {@link #VERSION_GRADLE_NAME version.gradle.kts} - * file. + * Finds a root of a project by presence of the {@link #VERSION_GRADLE version.gradle} or + * {@link #VERSION_GRADLE_KTS version.gradle.kts} file. * *

Starts from the current directory, climbing up, until the file is found. By convention - * a project should have only one {@link #VERSION_GRADLE_NAME version.gradle.kts} file, which is - * placed in the root directory of the project. + * a project should have only one version file, which is placed in the root directory of + * the project. */ enum ProjectRoot { INSTANCE; - private static final String VERSION_GRADLE_NAME = "version.gradle.kts"; + private static final String VERSION_GRADLE = "version.gradle"; + private static final String VERSION_GRADLE_KTS = "version.gradle.kts"; static ProjectRoot instance() { return INSTANCE; @@ -49,28 +50,33 @@ static ProjectRoot instance() { * Obtains a root directory of the project. * * @throws IllegalStateException - * if the {@link #VERSION_GRADLE_NAME version.gradle.kts} file is not found + * if the {@link #VERSION_GRADLE version.gradle.kts} file is not found */ Path toPath() { Path workingFolderPath = Paths.get(".") .toAbsolutePath(); Path extGradleDirPath = workingFolderPath; - while (extGradleDirPath != null - && !exists(extGradleDirPath.resolve(VERSION_GRADLE_NAME))) { + while (extGradleDirPath != null && !hasVersionGradle(extGradleDirPath)) { extGradleDirPath = extGradleDirPath.getParent(); } checkState(extGradleDirPath != null, - "%s file not found in %s or parent directories.", - VERSION_GRADLE_NAME, + "Neither `%s` nor `%s` found in `%s` or parent directories.", + VERSION_GRADLE, + VERSION_GRADLE_KTS, workingFolderPath); return extGradleDirPath; } + private static boolean hasVersionGradle(Path directory) { + return exists(directory.resolve(VERSION_GRADLE)) || + exists(directory.resolve(VERSION_GRADLE_KTS)); + } + /** * Obtains root directory of the project. * * @throws IllegalStateException - * if the {@link #VERSION_GRADLE_NAME version.gradle.kts} file is not found + * if the {@link #VERSION_GRADLE version.gradle.kts} file is not found * @see #toPath() */ File toFile() { diff --git a/tools/plugin-testlib/src/test/java/io/spine/tools/gradle/testing/MemoizingPluginRegistryTest.java b/tools/plugin-testlib/src/test/java/io/spine/tools/gradle/testing/MemoizingPluginRegistryTest.java index 0981fd3200..f0fb310b0d 100644 --- a/tools/plugin-testlib/src/test/java/io/spine/tools/gradle/testing/MemoizingPluginRegistryTest.java +++ b/tools/plugin-testlib/src/test/java/io/spine/tools/gradle/testing/MemoizingPluginRegistryTest.java @@ -46,7 +46,7 @@ void memoizePlugin() { @Test @DisplayName("memoize the given plugin script") void memoizePluginScript() { - PluginScript script = PluginScript.declaredIn(Resource.file(BuildGradle.FILE_NAME)); + PluginScript script = PluginScript.declaredIn(Resource.file(BuildGradle.BUILD_GRADLE)); MemoizingPluginRegistry registry = new MemoizingPluginRegistry(); registry.apply(script); assertThat(registry.pluginScripts()).containsExactly(script); diff --git a/tools/plugin-testlib/src/test/resources/build.gradle b/tools/plugin-testlib/src/test/resources/build.gradle.kts similarity index 87% rename from tools/plugin-testlib/src/test/resources/build.gradle rename to tools/plugin-testlib/src/test/resources/build.gradle.kts index 8c46ee78b8..84977f08fa 100644 --- a/tools/plugin-testlib/src/test/resources/build.gradle +++ b/tools/plugin-testlib/src/test/resources/build.gradle.kts @@ -18,9 +18,9 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -apply plugin: 'java' +val enclosingRootDir: String by extra +apply(plugin = "java") // NOTE: this file is copied from the root project in the test setup. -apply from: "$rootDir/test-env.gradle" - -apply from: "$enclosingRootDir/version.gradle.kts" +apply(from = "$rootDir/test-env.gradle") +apply(from = "$enclosingRootDir/version.gradle.kts") diff --git a/tools/proto-js-plugin/src/test/resources/build.gradle b/tools/proto-js-plugin/src/test/resources/build.gradle.kts similarity index 53% rename from tools/proto-js-plugin/src/test/resources/build.gradle rename to tools/proto-js-plugin/src/test/resources/build.gradle.kts index b26a4c8d17..3e9b4f9bce 100644 --- a/tools/proto-js-plugin/src/test/resources/build.gradle +++ b/tools/proto-js-plugin/src/test/resources/build.gradle.kts @@ -18,64 +18,63 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -buildscript { +import com.google.protobuf.gradle.* +import groovy.lang.GString +import io.spine.gradle.internal.Deps - // NOTE: this file is copied from the root project in the test setup. - apply from: "$rootDir/test-env.gradle" - - apply from: "$enclosingRootDir/config/gradle/dependencies.gradle" - apply from: "$enclosingRootDir/version.gradle.kts" +plugins { + java + @Suppress("RemoveRedundantQualifierName") // Cannot use imports here. + id("com.google.protobuf").version(io.spine.gradle.internal.Deps.versions.protobufPlugin) +} - repositories { - mavenLocal() - jcenter() - } +// NOTE: this file is copied from the root project in the test setup. +apply(from = "$rootDir/test-env.gradle") - dependencies { - classpath deps.build.gradlePlugins.protobuf - } -} +val enclosingRootDir: String by extra +apply(from = "$enclosingRootDir/version.gradle.kts") repositories { mavenLocal() jcenter() } -apply plugin: 'java' -apply plugin: 'com.google.protobuf' +tasks.compileJava { enabled = false } +tasks.compileTestJava { enabled = false } -project.compileJava.enabled = false -project.compileTestJava.enabled = false - -task compileProtoToJs +val compileProtoToJs by tasks.registering protobuf { generatedFilesBaseDir = "$projectDir/generated" protoc { - artifact = deps.build.protoc + artifact = Deps.build.protoc } generateProtoTasks { - all().each { final task -> + // Copy the task collection to avoid `ConcurrentModificationException`. + ArrayList(all()).forEach { task -> task.builtins { - remove java - - js { - option "import_style=commonjs" + remove("java") + id("js") { + option("import_style=commonjs") } } task.generateDescriptorSet = true - task.descriptorSetOptions.path = "${projectDir}/build/descriptors/${task.sourceSet.name}/known_types.desc" + task.descriptorSetOptions.path = GString.EMPTY.plus("${projectDir}/build/descriptors/${task.sourceSet.name}/known_types.desc") task.descriptorSetOptions.includeImports = true task.descriptorSetOptions.includeSourceInfo = true - compileProtoToJs.dependsOn task + compileProtoToJs.get().dependsOn(task) } } } -build.dependsOn compileProtoToJs +tasks.build { + dependsOn(compileProtoToJs) +} + +val spineVersion: String by extra dependencies { - protobuf files("${enclosingRootDir}/base/src/main/proto") - implementation "io.spine:spine-base:$spineVersion" + protobuf(files("$enclosingRootDir/base/src/main/proto")) + implementation("io.spine:spine-base:$spineVersion") } diff --git a/tools/smoke-tests/annotator-tests/build.gradle b/tools/smoke-tests/annotator-tests/build.gradle.kts similarity index 60% rename from tools/smoke-tests/annotator-tests/build.gradle rename to tools/smoke-tests/annotator-tests/build.gradle.kts index 925e7e8c36..485014e82f 100644 --- a/tools/smoke-tests/annotator-tests/build.gradle +++ b/tools/smoke-tests/annotator-tests/build.gradle.kts @@ -18,33 +18,38 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +import io.spine.gradle.internal.Deps + +plugins { + java + id("io.spine.tools.spine-model-compiler") +} + modelCompiler { generateAnnotations { - internal = 'io.spine.test.annotation.Private' - experimental = 'io.spine.test.annotation.Attempt' - beta = 'io.spine.test.annotation.Alpha' - spi = 'io.spine.test.annotation.ServiceProviderInterface' + internal = "io.spine.test.annotation.Private" + experimental = "io.spine.test.annotation.Attempt" + beta = "io.spine.test.annotation.Alpha" + spi = "io.spine.test.annotation.ServiceProviderInterface" } - internalClassPatterns += [ - '.*OrBuilder', // Classes ending with `OrBuilder`. - '.*Proto', // Classes ending with `Proto`. - '.*complex\\.Matter\\$.*[AaLl].*' + internalClassPatterns.addAll(listOf( + ".*OrBuilder", // Classes ending with `OrBuilder`. + ".*Proto", // Classes ending with `Proto`. + ".*complex\\.Matter\\$.*[AaLl].*" // Classes which have `complex.Matter$` in their FQN followed by an upper or lower // case letters ` A` or `L`. // For the sake of testing. This is not a recommended usage. - ] - internalMethodNames += [ - 'newBuilderForType', - 'parseFrom', - 'parseDelimitedFrom', - 'getSerializedSize', - 'internalGetValueMap' - ] + )) + internalMethodNames.addAll(listOf( + "newBuilderForType", + "parseFrom", + "parseDelimitedFrom", + "getSerializedSize", + "internalGetValueMap" + )) } dependencies { - testImplementation( - deps.grpc.grpcStub, - deps.grpc.grpcProtobuf - ) + testImplementation(Deps.grpc.stub) + testImplementation(Deps.grpc.protobuf) } diff --git a/tools/smoke-tests/build.gradle b/tools/smoke-tests/build.gradle deleted file mode 100644 index 9802cec52a..0000000000 --- a/tools/smoke-tests/build.gradle +++ /dev/null @@ -1,125 +0,0 @@ -/* - * Copyright 2020, TeamDev. All rights reserved. - * - * Redistribution and use in source and/or binary forms, with or without - * modification, must retain the above copyright notice and the following - * disclaimer. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -buildscript { - ext.baseRoot = "$rootDir/../.." - ext.versionGradle = "$baseRoot/version.gradle.kts" - - - apply from: versionGradle - apply from: "$baseRoot/config/gradle/dependencies.gradle" - - repositories { - maven { url = repos.gradlePlugins } - jcenter() - mavenLocal() - - maven { url = repos.oldSpine } - maven { url = repos.oldSpineSnapshots } - - maven { url = repos.spine } - maven { url = repos.spineSnapshots } - } - - - dependencies { - classpath deps.build.guava - classpath (deps.build.gradlePlugins.protobuf) { - exclude group: 'com.google.guava' - } - classpath (deps.build.gradlePlugins.errorProne) { - exclude group: 'com.google.guava' - } - // Always use the latest (current) version of model compiler no matter - // the global configuration. - classpath "io.spine.tools:spine-model-compiler:$spineVersion" - } -} - -allprojects { - apply from: versionGradle - apply plugin: 'java' - apply plugin: 'jacoco' - apply plugin: 'project-report' - - repositories { - mavenLocal() - jcenter() - } - - ext.baseRoot = "$rootDir/../.." -} - -subprojects { - apply plugin: 'com.google.protobuf' - apply plugin: 'io.spine.tools.spine-model-compiler' - apply plugin: 'idea' - apply from: "$baseRoot/config/gradle/test-output.gradle" - apply from: "$baseRoot/config/gradle/model-compiler.gradle" - - dependencies { - implementation( - deps.build.errorProneCore, - deps.build.errorProneAnnotations, - "io.spine:spine-base:$spineVersion" - ) - - testImplementation "io.spine:spine-testlib:$spineVersion" - testRuntimeOnly deps.test.junit5Runner - } - - forceConfiguration(project) - - idea.module { - generatedSourceDirs += file("$projectDir/generated/main/java") - generatedSourceDirs += file("$projectDir/generated/main/spine") - - generatedSourceDirs += file("$projectDir/generated/test/java") - generatedSourceDirs += file("$projectDir/generated/test/spine") - } - - sourceSets { - main { - proto.srcDirs "$projectDir/src/main/proto" - java.srcDirs "$projectDir/generated/main/java", - "$projectDir/generated/main/spine", - "$projectDir/src/main/java" - resources.srcDirs "$projectDir/generated/main/resources" - } - - test { - proto.srcDirs "$projectDir/src/test/proto" - java.srcDirs "$projectDir/generated/test/java", - "$projectDir/generated/test/spine", - "$projectDir/src/test/java" - resources.srcDirs "$projectDir/generated/test/resources" - } - } - - test { - useJUnitPlatform { - includeEngines 'junit-jupiter' - } - - include "**/*Test.class" - } -} - -apply from: "$baseRoot/config/gradle/jacoco.gradle" diff --git a/tools/smoke-tests/build.gradle.kts b/tools/smoke-tests/build.gradle.kts new file mode 100644 index 0000000000..832e32ee8b --- /dev/null +++ b/tools/smoke-tests/build.gradle.kts @@ -0,0 +1,133 @@ +/* + * Copyright 2020, TeamDev. All rights reserved. + * + * Redistribution and use in source and/or binary forms, with or without + * modification, must retain the above copyright notice and the following + * disclaimer. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +import io.spine.gradle.internal.DependencyResolution +import io.spine.gradle.internal.Deps + +buildscript { + + val baseRoot = "$rootDir/../.." + val versionGradle = "$baseRoot/version.gradle.kts" + + apply(from = versionGradle) + apply(from = "$baseRoot/config/gradle/dependencies.gradle") + + repositories { + gradlePluginPortal() + jcenter() + mavenLocal() + } + + val spineVersion: String by extra + + @Suppress("RemoveRedundantQualifierName") // Cannot use imports here. + val deps = io.spine.gradle.internal.Deps + dependencies { + classpath(deps.build.guava) + classpath(deps.build.gradlePlugins.protobuf) { + exclude(group = "com.google.guava") + } + classpath(deps.build.gradlePlugins.errorProne) { + exclude(group = "com.google.guava") + } + classpath("io.spine.tools:spine-model-compiler:$spineVersion") + } +} + +plugins { + java + idea + @Suppress("RemoveRedundantQualifierName") // Cannot use imports here. + id("com.google.protobuf").version(io.spine.gradle.internal.Deps.versions.protobufPlugin) +} + +val baseRoot = "$rootDir/../.." + +allprojects { + apply(from = "$baseRoot/version.gradle.kts") + apply(plugin = "java") + apply(plugin = "jacoco") + apply(plugin = "project-report") + + repositories { + mavenLocal() + jcenter() + } +} + +subprojects { + + apply { + plugin("com.google.protobuf") + plugin("io.spine.tools.spine-model-compiler") + plugin("idea") + from("$baseRoot/config/gradle/test-output.gradle") + from("$baseRoot/config/gradle/model-compiler.gradle") + } + + val spineVersion: String by extra + + dependencies { + implementation(Deps.build.errorProneCore) + Deps.build.errorProneAnnotations.forEach { implementation(it) } + implementation("io.spine:spine-base:$spineVersion") + testImplementation("io.spine:spine-testlib:$spineVersion") + testRuntimeOnly(Deps.test.junit5Runner) + } + + DependencyResolution.forceConfiguration(configurations) + + idea.module { + generatedSourceDirs.addAll(files( + "$projectDir/generated/main/java", + "$projectDir/generated/main/spine", + "$projectDir/generated/test/java", + "$projectDir/generated/test/spine" + )) + } + + sourceSets { + main { + proto.srcDir("$projectDir/src/main/proto") + java.srcDirs("$projectDir/generated/main/java", + "$projectDir/generated/main/spine", + "$projectDir/src/main/java") + resources.srcDir("$projectDir/generated/main/resources") + } + + test { + proto.srcDir("$projectDir/src/test/proto") + java.srcDirs("$projectDir/generated/test/java", + "$projectDir/generated/test/spine", + "$projectDir/src/test/java") + resources.srcDir("$projectDir/generated/test/resources") + } + } + + tasks.test { + useJUnitPlatform { + includeEngines("junit-jupiter") + } + + include("**/*Test.class") + } +} + +apply(from = "$baseRoot/config/gradle/jacoco.gradle") diff --git a/tools/smoke-tests/buildSrc/build.gradle.kts b/tools/smoke-tests/buildSrc/build.gradle.kts new file mode 100644 index 0000000000..7dc929afca --- /dev/null +++ b/tools/smoke-tests/buildSrc/build.gradle.kts @@ -0,0 +1,36 @@ +/* + * Copyright 2020, TeamDev. All rights reserved. + * + * Redistribution and use in source and/or binary forms, with or without + * modification, must retain the above copyright notice and the following + * disclaimer. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +plugins { + // Use Kotlin for `buildSrc`. + // https://kotlinlang.org/docs/reference/using-gradle.html#targeting-the-jvm + kotlin("jvm").version("1.3.72") +} + +repositories { + mavenLocal() + jcenter() +} + +val jacksonVersion = "2.11.0" + +dependencies { + implementation("com.fasterxml.jackson.dataformat:jackson-dataformat-xml:$jacksonVersion") +} diff --git a/tools/smoke-tests/buildSrc/src/main/kotlin/io/spine/gradle/internal/CheckVersionIncrement.kt b/tools/smoke-tests/buildSrc/src/main/kotlin/io/spine/gradle/internal/CheckVersionIncrement.kt new file mode 100644 index 0000000000..60709874e8 --- /dev/null +++ b/tools/smoke-tests/buildSrc/src/main/kotlin/io/spine/gradle/internal/CheckVersionIncrement.kt @@ -0,0 +1,104 @@ +/* + * Copyright 2020, TeamDev. All rights reserved. + * + * Redistribution and use in source and/or binary forms, with or without + * modification, must retain the above copyright notice and the following + * disclaimer. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package io.spine.gradle.internal + +import com.fasterxml.jackson.databind.DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES +import com.fasterxml.jackson.dataformat.xml.XmlMapper +import org.gradle.api.GradleException +import org.gradle.api.Project +import org.gradle.api.internal.AbstractTask +import org.gradle.api.tasks.Input +import org.gradle.api.tasks.TaskAction +import java.net.URL + +/** + * A task which verifies that the current version of the library has not been published to the given + * Maven repository yet. + */ +open class CheckVersionIncrement : AbstractTask() { + + /** + * The Maven repository in which to look for published artifacts. + * + * We only check the `releases` repository. Artifacts in `snapshots` repository still may be + * overridden. + */ + @Input + lateinit var repository: Repository + + @Input + private val version: String = project.version as String + + @TaskAction + private fun fetchAndCheck() { + val artifact = "${project.artifactPath()}/${MavenMetadata.FILE_NAME}" + val repoUrl = repository.releases + val metadata = fetch(repoUrl, artifact) + val versions = metadata.versioning.versions + val versionExists = versions.contains(version) + if (versionExists) { + throw GradleException(""" + Version `$version` is already published to maven repository `$repoUrl`. + Try incrementing the library version. + All available versions are: ${versions.joinToString(separator = ", ")}. + + To disable this check, run Gradle with `-x $name`. + """.trimIndent() + ) + } + } + + private fun fetch(repository: String, artifact: String): MavenMetadata { + val url = URL("$repository/$artifact") + return MavenMetadata.fetchAndParse(url) + } + + private fun Project.artifactPath(): String { + val group = this.group as String + val name = "spine-${this.name}" + + val pathElements = ArrayList(group.split('.')) + pathElements.add(name) + val path = pathElements.joinToString(separator = "/") + return path + } +} + +private data class MavenMetadata(var versioning: Versioning = Versioning()) { + + companion object { + + const val FILE_NAME = "maven-metadata.xml" + + private val mapper = XmlMapper() + + init { + mapper.configure(FAIL_ON_UNKNOWN_PROPERTIES, false) + } + + fun fetchAndParse(url: URL): MavenMetadata { + val metadata = mapper.readValue(url, MavenMetadata::class.java) + return metadata + } + } +} + +private data class Versioning(var versions: List = listOf()) diff --git a/tools/smoke-tests/buildSrc/src/main/kotlin/io/spine/gradle/internal/IncrementGuard.kt b/tools/smoke-tests/buildSrc/src/main/kotlin/io/spine/gradle/internal/IncrementGuard.kt new file mode 100644 index 0000000000..c227f49889 --- /dev/null +++ b/tools/smoke-tests/buildSrc/src/main/kotlin/io/spine/gradle/internal/IncrementGuard.kt @@ -0,0 +1,46 @@ +/* + * Copyright 2020, TeamDev. All rights reserved. + * + * Redistribution and use in source and/or binary forms, with or without + * modification, must retain the above copyright notice and the following + * disclaimer. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package io.spine.gradle.internal + +import org.gradle.api.Plugin +import org.gradle.api.Project + +/** + * Gradle plugin which adds a [CheckVersionIncrement] task. + * + * The task is called `checkVersionIncrement` inserted before the `check` task. + */ +class IncrementGuard : Plugin { + + companion object { + const val taskName = "checkVersionIncrement" + } + + override fun apply(target: Project) { + val tasks = target.tasks + tasks.register(taskName, CheckVersionIncrement::class.java) { + it.repository = PublishingRepos.cloudRepo + tasks.getByName("check").dependsOn(it) + + it.shouldRunAfter("test") + } + } +} diff --git a/tools/smoke-tests/buildSrc/src/main/kotlin/io/spine/gradle/internal/RunBuild.kt b/tools/smoke-tests/buildSrc/src/main/kotlin/io/spine/gradle/internal/RunBuild.kt new file mode 100644 index 0000000000..c083ad952a --- /dev/null +++ b/tools/smoke-tests/buildSrc/src/main/kotlin/io/spine/gradle/internal/RunBuild.kt @@ -0,0 +1,90 @@ +/* + * Copyright 2020, TeamDev. All rights reserved. + * + * Redistribution and use in source and/or binary forms, with or without + * modification, must retain the above copyright notice and the following + * disclaimer. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package io.spine.gradle.internal + +import org.gradle.api.GradleException +import org.gradle.api.internal.AbstractTask +import org.gradle.api.tasks.TaskAction +import org.gradle.internal.os.OperatingSystem +import java.io.File + +/** + * A Gradle task which runs another Gradle build. + * + * Launches Gradle wrapper under a given [directory] with the `build` task. The `clean` task is also + * run if current build includes a `clean` task. + * + * The build writes verbose log into `$directory/build/debug-out.txt`. The error output is written + * into `$directory/build/error-out.txt`. + */ +open class RunBuild : AbstractTask() { + + /** + * Path to the directory which contains a Gradle wrapper script. + */ + lateinit var directory: String + + @TaskAction + private fun execute() { + val runsOnWindows = OperatingSystem.current().isWindows() + val script = if (runsOnWindows) "gradlew.bat" else "gradlew" + val command = buildCommand(script) + + // Ensure build error output log. + // Since we're executing this task in another process, we redirect error output to + // the file under the `build` directory. + val buildDir = File(directory, "build") + if (!buildDir.exists()) { + buildDir.mkdir() + } + val errorOut = File(buildDir, "error-out.txt") + val debugOut = File(buildDir, "debug-out.txt") + + val process = buildProcess(command, errorOut, debugOut) + if (process.waitFor() != 0) { + throw GradleException("Build FAILED. See $errorOut for details.") + } + } + + private fun buildCommand(script: String): List { + val command = mutableListOf() + command.add("${project.rootDir}/$script") + val shouldClean = project.gradle + .taskGraph + .hasTask(":clean") + if (shouldClean) { + command.add("clean") + } + command.add("build") + command.add("--console=plain") + command.add("--debug") + command.add("--stacktrace") + return command + } + + private fun buildProcess(command: List, errorOut: File, debugOut: File) = + ProcessBuilder() + .command(command) + .directory(project.file(directory)) + .redirectError(errorOut) + .redirectOutput(debugOut) + .start() +} diff --git a/tools/smoke-tests/buildSrc/src/main/kotlin/io/spine/gradle/internal/deps.kt b/tools/smoke-tests/buildSrc/src/main/kotlin/io/spine/gradle/internal/deps.kt new file mode 100644 index 0000000000..2636036af2 --- /dev/null +++ b/tools/smoke-tests/buildSrc/src/main/kotlin/io/spine/gradle/internal/deps.kt @@ -0,0 +1,345 @@ +/* + * Copyright 2020, TeamDev. All rights reserved. + * + * Redistribution and use in source and/or binary forms, with or without + * modification, must retain the above copyright notice and the following + * disclaimer. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package io.spine.gradle.internal + +import org.gradle.api.Project +import org.gradle.api.artifacts.ConfigurationContainer +import org.gradle.api.artifacts.dsl.RepositoryHandler +import java.net.URI + +/* + * This file describes shared dependencies of Spine sub-projects. + * + * Inspired by dependency management of the Uber's NullAway project: + * https://github.com/uber/NullAway/blob/master/gradle/dependencies.gradle + */ + +data class Repository(val releases: String, + val snapshots: String, + val credentials: String) + +/** + * Repositories to which we may publish. Normally, only one repository will be used. + * + * See `publish.gradle` for details of the publishing process. + */ +object PublishingRepos { + val mavenTeamDev = Repository( + releases = "http://maven.teamdev.com/repository/spine", + snapshots = "http://maven.teamdev.com/repository/spine-snapshots", + credentials = "credentials.properties" + ) + val cloudRepo = Repository( + releases = "https://spine.mycloudrepo.io/public/repositories/releases", + snapshots = "https://spine.mycloudrepo.io/public/repositories/snapshots", + credentials = "cloudrepo.properties" + ) +} + +// Specific repositories. +object Repos { + val oldSpine: String = PublishingRepos.mavenTeamDev.releases + val oldSpineSnapshots: String = PublishingRepos.mavenTeamDev.snapshots + + val spine: String = PublishingRepos.cloudRepo.releases + val spineSnapshots: String = PublishingRepos.cloudRepo.snapshots + + val sonatypeSnapshots: String = "https://oss.sonatype.org/content/repositories/snapshots" + val gradlePlugins = "https://plugins.gradle.org/m2/" +} + +object Versions { + val checkerFramework = "3.3.0" + val errorProne = "2.3.4" + val errorProneJavac = "9+181-r4173-1" // taken from here: https://github.com/tbroyer/gradle-errorprone-plugin/blob/v0.8/build.gradle.kts + val errorPronePlugin = "1.1.1" + val pmd = "6.20.0" + val checkstyle = "8.29" + val protobufPlugin = "0.8.12" + val appengineApi = "1.9.79" + val appenginePlugin = "2.2.0" + val findBugs = "3.0.2" + val guava = "29.0-jre" + val protobuf = "3.11.4" + val grpc = "1.28.1" + val flogger = "0.5.1" + val junit4 = "4.12" + val junit5 = "5.6.2" + val junitPlatform = "1.6.2" + val junitPioneer = "0.4.2" + val truth = "1.0.1" + val httpClient = "1.34.2" + val apacheHttpClient = "2.1.2" + val firebaseAdmin = "6.12.2" + val roaster = "2.21.2.Final" + val licensePlugin = "1.13" + val javaPoet = "1.12.1" + val autoService = "1.0-rc6" + val autoCommon = "0.10" + val jackson = "2.9.10.4" + val animalSniffer = "1.18" + val apiguardian = "1.1.0" + + /** + * Version of the SLF4J library. + * + * Spine used to log with SLF4J. Now we use Flogger. Whenever a coice comes up, we recommend to + * use the latter. + * + * Some third-party libraries may clash with different versions of the library. Thus, we specify + * this version and force it via [forceConfiguration(..)][DependencyResolution.forceConfiguration]. + */ + @Deprecated("Use Flogger over SLF4J.", replaceWith = ReplaceWith("flogger")) + val slf4j = "1.7.29" +} + +object GradlePlugins { + val errorProne = "net.ltgt.gradle:gradle-errorprone-plugin:${Versions.errorPronePlugin}" + val protobuf = "com.google.protobuf:protobuf-gradle-plugin:${Versions.protobufPlugin}" + val appengine = "com.google.cloud.tools:appengine-gradle-plugin:${Versions.appenginePlugin}" + val licenseReport = "com.github.jk1:gradle-license-report:${Versions.licensePlugin}" +} + +object Build { + val errorProneJavac = "com.google.errorprone:javac:${Versions.errorProneJavac}" + val errorProneAnnotations = listOf( + "com.google.errorprone:error_prone_annotations:${Versions.errorProne}", + "com.google.errorprone:error_prone_type_annotations:${Versions.errorProne}" + ) + val errorProneCheckApi = "com.google.errorprone:error_prone_check_api:${Versions.errorProne}" + val errorProneCore = "com.google.errorprone:error_prone_core:${Versions.errorProne}" + val errorProneTestHelpers = "com.google.errorprone:error_prone_test_helpers:${Versions.errorProne}" + val checkerAnnotations = "org.checkerframework:checker-qual:${Versions.checkerFramework}" + val checkerDataflow = listOf( + "org.checkerframework:dataflow:${Versions.checkerFramework}", + "org.checkerframework:javacutil:${Versions.checkerFramework}" + ) + val autoCommon = "com.google.auto:auto-common:${Versions.autoCommon}" + val autoService = AutoService + val jsr305Annotations = "com.google.code.findbugs:jsr305:${Versions.findBugs}" + val guava = "com.google.guava:guava:${Versions.guava}" + val flogger = "com.google.flogger:flogger:${Versions.flogger}" + val protobuf = listOf( + "com.google.protobuf:protobuf-java:${Versions.protobuf}", + "com.google.protobuf:protobuf-java-util:${Versions.protobuf}" + ) + val protoc = "com.google.protobuf:protoc:${Versions.protobuf}" + val googleHttpClient = "com.google.http-client:google-http-client:${Versions.httpClient}" + val googleHttpClientApache = "com.google.http-client:google-http-client-apache:${Versions.apacheHttpClient}" + val appengineApi = "com.google.appengine:appengine-api-1.0-sdk:${Versions.appengineApi}" + val firebaseAdmin = "com.google.firebase:firebase-admin:${Versions.firebaseAdmin}" + val jacksonDatabind = "com.fasterxml.jackson.core:jackson-databind:${Versions.jackson}" + val roasterApi = "org.jboss.forge.roaster:roaster-api:${Versions.roaster}" + val roasterJdt = "org.jboss.forge.roaster:roaster-jdt:${Versions.roaster}" + val animalSniffer = "org.codehaus.mojo:animal-sniffer-annotations:${Versions.animalSniffer}" + val ci = "true".equals(System.getenv("CI")) + val gradlePlugins = GradlePlugins + @Deprecated("Use Flogger over SLF4J.", replaceWith = ReplaceWith("flogger")) + @Suppress("DEPRECATION") // Version of SLF4J. + val slf4j = "org.slf4j:slf4j-api:${Versions.slf4j}" + + object AutoService { + val annotations = "com.google.auto.service:auto-service-annotations:${Versions.autoService}" + val processor = "com.google.auto.service:auto-service:${Versions.autoService}" + } +} + +object Gen { + val javaPoet = "com.squareup:javapoet:${Versions.javaPoet}" +} + +object Grpc { + val core = "io.grpc:grpc-core:${Versions.grpc}" + val stub = "io.grpc:grpc-stub:${Versions.grpc}" + val okHttp = "io.grpc:grpc-okhttp:${Versions.grpc}" + val protobuf = "io.grpc:grpc-protobuf:${Versions.grpc}" + val netty = "io.grpc:grpc-netty:${Versions.grpc}" + val nettyShaded = "io.grpc:grpc-netty-shaded:${Versions.grpc}" + val context = "io.grpc:grpc-context:${Versions.grpc}" + + @Deprecated("Use the shorter form.", replaceWith = ReplaceWith("core")) + val grpcCore = core + @Deprecated("Use the shorter form.", replaceWith = ReplaceWith("stub")) + val grpcStub = stub + @Deprecated("Use the shorter form.", replaceWith = ReplaceWith("okHttp")) + val grpcOkHttp = okHttp + @Deprecated("Use the shorter form.", replaceWith = ReplaceWith("protobuf")) + val grpcProtobuf = protobuf + @Deprecated("Use the shorter form.", replaceWith = ReplaceWith("netty")) + val grpcNetty = netty + @Deprecated("Use the shorter form.", replaceWith = ReplaceWith("nettyShaded")) + val grpcNettyShaded = nettyShaded + @Deprecated("Use the shorter form.", replaceWith = ReplaceWith("context")) + val grpcContext = context +} + +object Runtime { + + val flogger = Flogger + + object Flogger { + val systemBackend = "com.google.flogger:flogger-system-backend:${Versions.flogger}" + val log4J = "com.google.flogger:flogger-log4j:${Versions.flogger}" + val slf4J = "com.google.flogger:slf4j-backend-factory:${Versions.flogger}" + } + + @Deprecated("Use the `flogger` object.", replaceWith = ReplaceWith("flogger.systemBackend")) + val floggerSystemBackend = flogger.systemBackend + @Deprecated("Use the `flogger` object.", replaceWith = ReplaceWith("flogger.log4J")) + val floggerLog4J = flogger.log4J + @Deprecated("Use the `flogger` object.", replaceWith = ReplaceWith("flogger.slf4J")) + val floggerSlf4J = flogger.slf4J +} + +object Test { + val junit4 = "junit:junit:${Versions.junit4}" + val junit5Api = listOf( + "org.junit.jupiter:junit-jupiter-api:${Versions.junit5}", + "org.junit.jupiter:junit-jupiter-params:${Versions.junit5}", + "org.apiguardian:apiguardian-api:${Versions.apiguardian}" + ) + val junit5Runner = "org.junit.jupiter:junit-jupiter-engine:${Versions.junit5}" + val junitPioneer = "org.junit-pioneer:junit-pioneer:${Versions.junitPioneer}" + val guavaTestlib = "com.google.guava:guava-testlib:${Versions.guava}" + val mockito = "org.mockito:mockito-core:2.12.0" + val hamcrest = "org.hamcrest:hamcrest-all:1.3" + val truth = listOf( + "com.google.truth:truth:${Versions.truth}", + "com.google.truth.extensions:truth-java8-extension:${Versions.truth}", + "com.google.truth.extensions:truth-proto-extension:${Versions.truth}" + ) + @Deprecated("Use Flogger over SLF4J.", + replaceWith = ReplaceWith("Deps.runtime.floggerSystemBackend")) + @Suppress("DEPRECATION") // Version of SLF4J. + val slf4j = "org.slf4j:slf4j-jdk14:${Versions.slf4j}" +} + +object Scripts { + + private const val COMMON_PATH = "/config/gradle/" + + fun testArtifacts(p: Project) = p.script("test-artifacts.gradle") + fun testOutput(p: Project) = p.script("test-output.gradle") + fun slowTests(p: Project) = p.script("slow-tests.gradle") + fun javadocOptions(p: Project) = p.script("javadoc-options.gradle") + fun filterInternalJavadocs(p: Project) = p.script("filter-internal-javadoc.gradle") + fun jacoco(p: Project) = p.script("jacoco.gradle") + fun publish(p: Project) = p.script("publish.gradle") + fun publishProto(p: Project) = p.script("publish-proto.gradle") + fun javacArgs(p: Project) = p.script("javac-args.gradle") + fun jsBuildTasks(p: Project) = p.script("js/build-tasks.gradle") + fun jsConfigureProto(p: Project) = p.script("js/configure-proto.gradle") + fun npmPublishTasks(p: Project) = p.script("js/npm-publish-tasks.gradle") + fun npmCli(p: Project) = p.script("js/npm-cli.gradle") + fun updatePackageVersion(p: Project) = p.script("js/update-package-version.gradle") + fun dartBuildTasks(p: Project) = p.script("dart/build-tasks.gradle") + fun pubPublishTasks(p: Project) = p.script("dart/pub-publish-tasks.gradle") + fun pmd(p: Project) = p.script("pmd.gradle") + fun checkstyle(p: Project) = p.script("checkstyle.gradle") + fun runBuild(p: Project) = p.script("run-build.gradle") + fun modelCompiler(p: Project) = p.script("model-compiler.gradle") + fun licenseReportCommon(p: Project) = p.script("license-report-common.gradle") + fun projectLicenseReport(p: Project) = p.script("license-report-project.gradle") + fun repoLicenseReport(p: Project) = p.script("license-report-repo.gradle") + fun generatePom(p: Project) = p.script("generate-pom.gradle") + fun updateGitHubPages(p: Project) = p.script("update-gh-pages.gradle") + + private fun Project.script(name: String) = "${rootDir}$COMMON_PATH$name" +} + +object Deps { + val build = Build + val grpc = Grpc + val gen = Gen + val runtime = Runtime + val test = Test + val versions = Versions + val scripts = Scripts +} + +object DependencyResolution { + + fun forceConfiguration(configurations: ConfigurationContainer) { + configurations.all { config -> + config.resolutionStrategy { strategy -> + strategy.failOnVersionConflict() + strategy.cacheChangingModulesFor(0, "seconds") + @Suppress("DEPRECATION") // Force SLF4J version. + strategy.force( + Deps.build.slf4j, + Deps.build.errorProneAnnotations, + Deps.build.jsr305Annotations, + Deps.build.checkerAnnotations, + Deps.build.autoCommon, + Deps.build.guava, + Deps.build.animalSniffer, + Deps.build.protobuf, + Deps.test.guavaTestlib, + Deps.test.truth, + Deps.test.junit5Api, + Deps.test.junit4, + + // Transitive dependencies of 3rd party components that we don't use directly. + "com.google.code.gson:gson:2.8.6", + "com.google.j2objc:j2objc-annotations:1.3", + "org.codehaus.plexus:plexus-utils:3.3.0", + "com.squareup.okio:okio:1.17.5", // Last version before next major. + "commons-cli:commons-cli:1.4", + + // Force discontinued transitive dependency until everybody migrates off it. + "org.checkerframework:checker-compat-qual:2.5.5", + + "commons-logging:commons-logging:1.2", + + // Force the Gradle Protobuf plugin version. + Deps.build.gradlePlugins.protobuf + ) + } + } + } + + fun excludeProtobufLite(configurations: ConfigurationContainer) { + excludeProtoLite(configurations, "runtime") + excludeProtoLite(configurations, "testRuntime") + } + + private fun excludeProtoLite(configurations: ConfigurationContainer, + configurationName: String) { + configurations.named(configurationName).get() + .exclude(mapOf("group" to "com.google.protobuf", "module" to "protobuf-lite")) + } + + fun defaultRepositories(repositories: RepositoryHandler) { + repositories.mavenLocal() + repositories.maven { repository -> + repository.url = URI(Repos.spine) + repository.content { descriptor -> + descriptor.includeGroup("io.spine") + descriptor.includeGroup("io.spine.tools") + descriptor.includeGroup("io.spine.gcloud") + } + } + repositories.jcenter() + repositories.maven { repository -> + repository.url = URI(Repos.gradlePlugins) + } + } +} diff --git a/tools/smoke-tests/column-tests/build.gradle b/tools/smoke-tests/column-tests/build.gradle.kts similarity index 86% rename from tools/smoke-tests/column-tests/build.gradle rename to tools/smoke-tests/column-tests/build.gradle.kts index a049867a18..d90a79a926 100644 --- a/tools/smoke-tests/column-tests/build.gradle +++ b/tools/smoke-tests/column-tests/build.gradle.kts @@ -18,8 +18,12 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +plugins { + id("io.spine.tools.spine-model-compiler") +} + modelCompiler { fields { - generateFor "spine.tools.column.ProjectName", markAs("io.spine.tools.protoc.given.ProjectNameField") + generateFor("spine.tools.column.ProjectName", markAs("io.spine.tools.protoc.given.ProjectNameField")) } } diff --git a/tools/smoke-tests/known-types-tests/build.gradle b/tools/smoke-tests/generated-validation-tests/build.gradle.kts similarity index 81% rename from tools/smoke-tests/known-types-tests/build.gradle rename to tools/smoke-tests/generated-validation-tests/build.gradle.kts index 7fda8353ec..883b1dfdc0 100644 --- a/tools/smoke-tests/known-types-tests/build.gradle +++ b/tools/smoke-tests/generated-validation-tests/build.gradle.kts @@ -18,12 +18,18 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -/* - This Smoke Tests module verifies correctness of composition of {@code KnownTypes}. - No additional config is required. - See smoke-tests/build.gradle for all the config of the project. -*/ +import io.spine.gradle.internal.Deps + +plugins { + java + id("io.spine.tools.spine-model-compiler") +} modelCompiler { generateValidation = true } + +dependencies { + testAnnotationProcessor(Deps.build.autoService.processor) + testCompileOnly(Deps.build.autoService.annotations) +} diff --git a/tools/smoke-tests/gradle/wrapper/gradle-wrapper.jar b/tools/smoke-tests/gradle/wrapper/gradle-wrapper.jar index 490fda8577..62d4c05355 100644 Binary files a/tools/smoke-tests/gradle/wrapper/gradle-wrapper.jar and b/tools/smoke-tests/gradle/wrapper/gradle-wrapper.jar differ diff --git a/tools/smoke-tests/gradle/wrapper/gradle-wrapper.properties b/tools/smoke-tests/gradle/wrapper/gradle-wrapper.properties index 4c5803d13c..a4f0001d20 100644 --- a/tools/smoke-tests/gradle/wrapper/gradle-wrapper.properties +++ b/tools/smoke-tests/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-6.4-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-6.4.1-bin.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/tools/smoke-tests/gradlew b/tools/smoke-tests/gradlew index 2fe81a7d95..fbd7c51583 100755 --- a/tools/smoke-tests/gradlew +++ b/tools/smoke-tests/gradlew @@ -82,6 +82,7 @@ esac CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar + # Determine the Java command to use to start the JVM. if [ -n "$JAVA_HOME" ] ; then if [ -x "$JAVA_HOME/jre/sh/java" ] ; then @@ -129,6 +130,7 @@ fi if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then APP_HOME=`cygpath --path --mixed "$APP_HOME"` CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` + JAVACMD=`cygpath --unix "$JAVACMD"` # We build the pattern for arguments to be converted via cygpath diff --git a/tools/smoke-tests/gradlew.bat b/tools/smoke-tests/gradlew.bat index 62bd9b9cce..5093609d51 100644 --- a/tools/smoke-tests/gradlew.bat +++ b/tools/smoke-tests/gradlew.bat @@ -84,6 +84,7 @@ set CMD_LINE_ARGS=%* set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + @rem Execute Gradle "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% diff --git a/tools/smoke-tests/generated-validation-tests/build.gradle b/tools/smoke-tests/known-types-tests/build.gradle.kts similarity index 89% rename from tools/smoke-tests/generated-validation-tests/build.gradle rename to tools/smoke-tests/known-types-tests/build.gradle.kts index 40f520727c..71b5a63633 100644 --- a/tools/smoke-tests/generated-validation-tests/build.gradle +++ b/tools/smoke-tests/known-types-tests/build.gradle.kts @@ -18,11 +18,10 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -modelCompiler { - generateValidation = true +plugins { + id("io.spine.tools.spine-model-compiler") } -dependencies { - testAnnotationProcessor deps.build.autoService.processor - testCompileOnly deps.build.autoService.annotations +modelCompiler { + generateValidation = true } diff --git a/tools/smoke-tests/model-compiler-tests/build.gradle b/tools/smoke-tests/model-compiler-tests/build.gradle deleted file mode 100644 index f0284350d1..0000000000 --- a/tools/smoke-tests/model-compiler-tests/build.gradle +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright 2020, TeamDev. All rights reserved. - * - * Redistribution and use in source and/or binary forms, with or without - * modification, must retain the above copyright notice and the following - * disclaimer. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -dependencies { - testImplementation project(':test-factories') - testImplementation deps.test.truth -} - -modelCompiler { - - interfaces { - mark messages().inFiles(suffix: 'documents.proto'), asType('io.spine.tools.protoc.DocumentMessage') - mark messages().inFiles(prefix: 'spine/tools/protoc/prefix_generation'), asType('io.spine.tools.protoc.PrefixedMessage') - mark messages().inFiles(suffix: 'suffix_generation_test.proto'), asType('io.spine.tools.protoc.SuffixedMessage') - mark messages().inFiles(regex: '.*regex.*test.*'), asType('io.spine.tools.protoc.RegexedMessage') - } - - methods { - applyFactory "io.spine.tools.protoc.TestMethodFactory", messages().inFiles(suffix: 'suffix_generation_test.proto') - applyFactory "io.spine.tools.protoc.TestMethodFactory", messages().inFiles(prefix: 'spine/tools/protoc/prefix_generation') - applyFactory "io.spine.tools.protoc.TestMethodFactory", messages().inFiles(regex: '.*regex.*test.*') - applyFactory "io.spine.tools.protoc.TestMethodFactory", messages().inFiles(regex: '.*multi.*factory.*test.*') - } - - nestedClasses { - applyFactory "io.spine.tools.protoc.TestNestedClassFactory", messages().inFiles(suffix: 'suffix_generation_test.proto') - applyFactory "io.spine.tools.protoc.TestNestedClassFactory", messages().inFiles(prefix: 'spine/tools/protoc/prefix_generation') - applyFactory "io.spine.tools.protoc.TestNestedClassFactory", messages().inFiles(regex: '.*regex.*test.*') - } -} diff --git a/tools/smoke-tests/model-compiler-tests/build.gradle.kts b/tools/smoke-tests/model-compiler-tests/build.gradle.kts new file mode 100644 index 0000000000..1288ab05b0 --- /dev/null +++ b/tools/smoke-tests/model-compiler-tests/build.gradle.kts @@ -0,0 +1,59 @@ +/* + * Copyright 2020, TeamDev. All rights reserved. + * + * Redistribution and use in source and/or binary forms, with or without + * modification, must retain the above copyright notice and the following + * disclaimer. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +import io.spine.gradle.internal.Deps +import io.spine.tools.protoc.MessageSelectorFactory.prefix +import io.spine.tools.protoc.MessageSelectorFactory.regex +import io.spine.tools.protoc.MessageSelectorFactory.suffix + +plugins { + java + id("io.spine.tools.spine-model-compiler") +} + +dependencies { + testImplementation(project(":test-factories")) + Deps.test.truth.forEach { testImplementation(it) } +} + +modelCompiler { + + interfaces { + mark(messages().inFiles(suffix("documents.proto")), asType("io.spine.tools.protoc.DocumentMessage")) + mark(messages().inFiles(prefix("spine/tools/protoc/prefix_generation")), asType("io.spine.tools.protoc.PrefixedMessage")) + mark(messages().inFiles(suffix("suffix_generation_test.proto")), asType("io.spine.tools.protoc.SuffixedMessage")) + mark(messages().inFiles(regex(".*regex.*test.*")), asType("io.spine.tools.protoc.RegexedMessage")) + } + + methods { + val factory = "io.spine.tools.protoc.TestMethodFactory" + applyFactory(factory, messages().inFiles(suffix("suffix_generation_test.proto"))) + applyFactory(factory, messages().inFiles(prefix("spine/tools/protoc/prefix_generation"))) + applyFactory(factory, messages().inFiles(regex(".*regex.*test.*"))) + applyFactory(factory, messages().inFiles(regex(".*multi.*factory.*test.*"))) + } + + nestedClasses { + val factory = "io.spine.tools.protoc.TestNestedClassFactory" + applyFactory(factory, messages().inFiles(suffix("suffix_generation_test.proto"))) + applyFactory(factory, messages().inFiles(prefix("spine/tools/protoc/prefix_generation"))) + applyFactory(factory, messages().inFiles(regex(".*regex.*test.*"))) + } +} diff --git a/tools/smoke-tests/rejection-tests/build.gradle b/tools/smoke-tests/rejection-tests/build.gradle.kts similarity index 100% rename from tools/smoke-tests/rejection-tests/build.gradle rename to tools/smoke-tests/rejection-tests/build.gradle.kts diff --git a/tools/smoke-tests/settings.gradle b/tools/smoke-tests/settings.gradle.kts similarity index 70% rename from tools/smoke-tests/settings.gradle rename to tools/smoke-tests/settings.gradle.kts index 6fb4f1e0c6..66da9578b6 100644 --- a/tools/smoke-tests/settings.gradle +++ b/tools/smoke-tests/settings.gradle.kts @@ -18,27 +18,27 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -include 'annotator-tests' -include 'column-tests' -include 'generated-validation-tests' -include 'known-types-tests' -include 'model-compiler-tests' -include 'rejection-tests' -include 'test-factories' -include 'validating-options-tests' -include 'validation-tests' +include("annotator-tests") +include("column-tests") +include("generated-validation-tests") +include("known-types-tests") +include("model-compiler-tests") +include("rejection-tests") +include("test-factories") +include("validating-options-tests") +include("validation-tests") /* * Dependency links established with the Gradle included build. * * See the `includeBuild(...)` block below for more info. */ -final def links = [ - 'io.spine:spine-base' : ':base', - 'io.spine.tools:spine-tool-base' : ':tool-base', - 'io.spine.tools:spine-model-compiler' : ':model-compiler', - 'io.spine:spine-testlib' : ':testlib' -] +val links = mapOf( + "io.spine:spine-base" to ":base", + "io.spine.tools:spine-tool-base" to ":tool-base", + "io.spine.tools:spine-model-compiler" to ":model-compiler", + "io.spine:spine-testlib" to ":testlib" +) /* * Include the `base` build into `smoke-test` project build. @@ -51,8 +51,8 @@ final def links = [ */ includeBuild("$rootDir/../../") { dependencySubstitution { - links.each { - substitute module(it.key) with project(it.value) + links.forEach { id, projectPath -> + substitute(module(id)).with(project(projectPath)) } } } diff --git a/tools/smoke-tests/test-factories/build.gradle b/tools/smoke-tests/test-factories/build.gradle.kts similarity index 90% rename from tools/smoke-tests/test-factories/build.gradle rename to tools/smoke-tests/test-factories/build.gradle.kts index 767683c1e3..7471b88210 100644 --- a/tools/smoke-tests/test-factories/build.gradle +++ b/tools/smoke-tests/test-factories/build.gradle.kts @@ -18,10 +18,16 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +import io.spine.gradle.internal.Deps + /* This Smoke Tests module holds a TestMethodFactory that is used in model-compiler-test module. */ -dependencies{ - implementation deps.gen.javaPoet +plugins { + java +} + +dependencies { + implementation(Deps.gen.javaPoet) } diff --git a/tools/validation-generator/build.gradle b/tools/smoke-tests/validating-options-tests/build.gradle.kts similarity index 85% rename from tools/validation-generator/build.gradle rename to tools/smoke-tests/validating-options-tests/build.gradle.kts index 0bc445ba47..35d9ebecd2 100644 --- a/tools/validation-generator/build.gradle +++ b/tools/smoke-tests/validating-options-tests/build.gradle.kts @@ -18,11 +18,13 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -group = 'io.spine.tools' +import io.spine.gradle.internal.Deps + +plugins { + java +} dependencies { - api deps.gen.javaPoet - implementation project(':tool-base') - testImplementation project(':base') - testImplementation project(':testlib') + testAnnotationProcessor(Deps.build.autoService.processor) + testCompileOnly(Deps.build.autoService.annotations) } diff --git a/tools/smoke-tests/validation-tests/build.gradle b/tools/smoke-tests/validation-tests/build.gradle.kts similarity index 100% rename from tools/smoke-tests/validation-tests/build.gradle rename to tools/smoke-tests/validation-tests/build.gradle.kts diff --git a/tools/smoke-tests/validating-options-tests/build.gradle b/tools/validation-generator/build.gradle.kts similarity index 82% rename from tools/smoke-tests/validating-options-tests/build.gradle rename to tools/validation-generator/build.gradle.kts index 7b9c371cbe..b439f94b93 100644 --- a/tools/smoke-tests/validating-options-tests/build.gradle +++ b/tools/validation-generator/build.gradle.kts @@ -18,7 +18,13 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +import io.spine.gradle.internal.Deps + +group = "io.spine.tools" + dependencies { - testAnnotationProcessor deps.build.autoService.processor - testCompileOnly deps.build.autoService.annotations + api(Deps.gen.javaPoet) + implementation(project(":tool-base")) + testImplementation(project(":base")) + testImplementation(project(":testlib")) } diff --git a/version.gradle.kts b/version.gradle.kts index d307d56558..211c55daa5 100644 --- a/version.gradle.kts +++ b/version.gradle.kts @@ -25,7 +25,7 @@ * as we want to manage the versions in a single source. */ -val SPINE_VERSION = "1.5.11" +val SPINE_VERSION = "1.5.12" project.extra.apply { this["spineVersion"] = SPINE_VERSION