blob: 91d8bdf099a8f66b2d3bf8c2f65c30122c545cf8 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
import com.github.spotbugs.SpotBugsTask
import org.nosphere.apache.rat.RatTask
import java.nio.file.Files
import java.nio.file.Paths
buildscript {
dependencies {
// findBugs needs a newer version of Guava in the buildscript.
// otherwise it throws an exception
classpath "com.google.guava:guava:28.2-jre"
}
}
plugins {
id 'idea'
id 'java'
id 'java-test-fixtures'
id 'application'
id 'maven-publish'
// since we're using a specific version here, we delay applying the plugin till the all projects
id "com.github.spotbugs" version "3.0.0" apply false
// https://github.com/nebula-plugins/gradle-ospackage-plugin/wiki
id "nebula.ospackage" version "8.3.0"
id 'nebula.ospackage-application' version "8.3.0"
id 'com.google.cloud.tools.jib' version '2.2.0'
id 'org.asciidoctor.jvm.convert' version '3.1.0'
// Release Audit Tool (RAT) plugin for checking project licenses
id("org.nosphere.apache.rat") version "0.8.0"
}
println("Using DTest jar: ${dtestVersion}")
def integrationMaxHeapSize = System.getenv("INTEGRATION_MAX_HEAP_SIZE") ?: "8g"
println("Using ${integrationMaxHeapSize} maxHeapSize")
def integrationMaxParallelForks = (System.getenv("INTEGRATION_MAX_PARALLEL_FORKS") ?: "4") as int
println("Using ${integrationMaxParallelForks} maxParallelForks")
// Force checkstyle, rat, and spotBugs to run before test tasks for faster feedback
def codeCheckTasks = task("codeCheckTasks")
allprojects {
apply plugin: 'jacoco'
apply plugin: 'checkstyle'
apply plugin: "com.github.spotbugs"
repositories {
mavenCentral()
// for dtest jar
mavenLocal()
}
checkstyle {
toolVersion '7.8.1'
configFile file("${project.rootDir}/checkstyle.xml")
}
spotbugs {
toolVersion = '4.2.3'
excludeFilter = file("${project.rootDir}/spotbugs-exclude.xml")
}
tasks.withType(SpotBugsTask) {
reports.xml.enabled = false
reports.html.enabled = true
}
codeCheckTasks.dependsOn(tasks.withType(Checkstyle))
codeCheckTasks.dependsOn(tasks.withType(RatTask))
codeCheckTasks.dependsOn(tasks.withType(SpotBugsTask))
tasks.withType(Test) {
shouldRunAfter(codeCheckTasks)
shouldRunAfter(tasks.withType(Checkstyle))
shouldRunAfter(tasks.withType(RatTask))
shouldRunAfter(tasks.withType(SpotBugsTask))
}
}
group 'org.apache.cassandra'
version project.version
sourceCompatibility = 1.8
// Take the application out once we're running via Cassandra
mainClassName = "org.apache.cassandra.sidecar.CassandraSidecarDaemon"
applicationName = 'cassandra-sidecar'
// Config file location should be in file:/// format for local files,
def confFile = "file:" + File.separator + File.separator + "APP_HOME_TO_REPLACE/conf/sidecar.yaml"
applicationDefaultJvmArgs = ["-Dsidecar.logdir=./logs",
"-Dsidecar.config=" + confFile,
"-Dlogback.configurationFile=./conf/logback.xml",
"-Dvertx.logger-delegate-factory-class-name=io.vertx.core.logging.SLF4JLogDelegateFactory",
"-javaagent:APP_HOME_TO_REPLACE/agents/jolokia-jvm-1.6.0-agent.jar=port=7777,host=localhost"]
startScripts {
doLast {
unixScript.text = unixScript.text.replace("APP_HOME_TO_REPLACE", "\${APP_HOME}")
}
}
run {
confFile = "file:" + File.separator + File.separator + "$projectDir/conf/sidecar.yaml"
println "Sidecar configuration file $confFile"
jvmArgs = ["-Dsidecar.logdir=./logs",
"-Dsidecar.config=" + confFile,
"-Dlogback.configurationFile=./conf/logback.xml",
"-Dvertx.logger-delegate-factory-class-name=io.vertx.core.logging.SLF4JLogDelegateFactory",
"-javaagent:$projectDir/agents/jolokia-jvm-1.6.0-agent.jar=port=7777,host=localhost"]
}
// add additional test source set
sourceSets {
integrationTest {
java {
compileClasspath += main.output + test.output
runtimeClasspath += main.output + test.output
srcDir file('src/test/integration')
}
}
containerTest {
java {
compileClasspath += main.output + test.output
runtimeClasspath += main.output + test.output
srcDir file('src/test/containerTest')
}
}
}
// and mark it as test root
idea {
module {
testSourceDirs += sourceSets.integrationTest.java.srcDirs
testSourceDirs += sourceSets.containerTest.java.srcDirs
}
}
configurations {
jolokia
integrationTestImplementation.extendsFrom testImplementation
containerTestImplementation.extendsFrom testImplementation
runtime.exclude(group: "com.google.code.findbugs", module: "jsr305")
runtime.exclude(group: "org.codehaus.mojo", module: "animal-sniffer-annotations")
runtime.exclude(group: "com.google.guava", module: "listenablefuture")
runtime.exclude(group: "org.checkerframework", module: "checker-qual")
runtime.exclude(group: "com.google.errorprone", module: "error_prone_annotations")
runtime.exclude(group: 'com.github.jnr', module: 'jnr-ffi')
runtime.exclude(group: 'com.github.jnr', module: 'jnr-posix')
}
dependencies {
compileOnly('org.jetbrains:annotations:23.0.0')
testCompileOnly('org.jetbrains:annotations:23.0.0')
integrationTestCompileOnly('org.jetbrains:annotations:23.0.0')
implementation("io.vertx:vertx-web:${project.vertxVersion}") {
exclude group: 'junit', module: 'junit'
}
implementation("io.vertx:vertx-dropwizard-metrics:${project.vertxVersion}")
implementation("io.vertx:vertx-web-client:${project.vertxVersion}")
implementation('com.datastax.cassandra:cassandra-driver-core:3.11.3')
implementation('com.google.inject:guice:4.2.2')
implementation("com.github.ben-manes.caffeine:caffeine:2.9.3")
// Trying to be exactly compatible with Cassandra's deps
implementation("org.slf4j:slf4j-api:${project.slf4jVersion}")
implementation('ch.qos.logback:logback-core:1.2.3')
implementation('ch.qos.logback:logback-classic:1.2.3')
implementation(group: 'org.apache.commons', name: 'commons-lang3', version: '3.13.0')
implementation(group: 'commons-codec', name: 'commons-codec', version: "${project.commonsCodecVersion}")
// Jackson for yaml-based configuration parsing
implementation(group: 'com.fasterxml.jackson.core', name: 'jackson-databind', version: "${project.jacksonVersion}")
implementation(group: 'com.fasterxml.jackson.dataformat', name: 'jackson-dataformat-yaml', version: "${project.jacksonVersion}")
// aws sdk BOM + s3
implementation platform(group: 'software.amazon.awssdk', name:'bom', version:"${project.aswSdkVersion}")
implementation('software.amazon.awssdk:s3')
implementation('software.amazon.awssdk:netty-nio-client')
jolokia 'org.jolokia:jolokia-jvm:1.6.0:agent'
testImplementation "org.junit.jupiter:junit-jupiter-api:${project.junitVersion}"
testImplementation "org.junit.jupiter:junit-jupiter-params:${project.junitVersion}"
testImplementation "org.assertj:assertj-core:3.24.2"
testRuntimeOnly "org.junit.jupiter:junit-jupiter-engine:${project.junitVersion}"
testImplementation('com.google.guava:guava-testlib:31.1-jre') {
exclude group: 'junit', module: 'junit'
}
testImplementation('com.datastax.cassandra:cassandra-driver-core:3.9.0:tests')
testImplementation('org.mockito:mockito-core:4.10.0')
testImplementation('org.mockito:mockito-inline:4.10.0')
testImplementation("io.vertx:vertx-junit5:${project.vertxVersion}")
testImplementation(testFixtures(project(":client-common")))
testImplementation(testFixtures(project(":server-common")))
implementation(project(":server-common"))
implementation(project(":adapters:base"))
implementation(project(":adapters:cassandra41"))
testFixturesApi(testFixtures(project(":server-common")))
testFixturesImplementation("io.vertx:vertx-junit5:${project.vertxVersion}")
testFixturesImplementation('com.google.inject:guice:4.2.2')
testFixturesImplementation('org.mockito:mockito-core:4.10.0')
testFixturesImplementation("org.junit.jupiter:junit-jupiter-api:${project.junitVersion}")
testFixturesImplementation("org.junit.jupiter:junit-jupiter-params:${project.junitVersion}")
testFixturesImplementation("org.assertj:assertj-core:3.24.2")
testFixturesImplementation("io.vertx:vertx-web:${project.vertxVersion}") {
exclude group: 'junit', module: 'junit'
}
integrationTestImplementation(group: 'org.apache.cassandra', name: "${dtestDependencyName}", version: "${dtestVersion}")
integrationTestImplementation(group: 'org.apache.cassandra', name: 'dtest-api', version: "${dtestApiVersion}")
integrationTestImplementation "org.junit.jupiter:junit-jupiter-api:${project.junitVersion}"
// Needed by the Cassandra dtest framework
integrationTestImplementation("org.junit.vintage:junit-vintage-engine:${junitVersion}")
// Needed for snapshot manifest validation
integrationTestImplementation(group: 'com.fasterxml.jackson.datatype', name: 'jackson-datatype-jsr310', version: "${project.jacksonVersion}")
containerTestImplementation('com.adobe.testing:s3mock-testcontainers:2.17.0') // 3.x version do not support java 11
}
jar {
doFirst {
// Store current Cassandra Sidecar build version in an embedded resource file;
// the file is either created or overwritten, and ignored by Git source control
Files.createDirectories(Paths.get("$projectDir/server-common/src/main/resources"))
new File("$projectDir/server-common/src/main/resources/sidecar.version").text = version
}
}
java {
withJavadocJar()
withSourcesJar()
}
publishing {
publications {
maven(MavenPublication) {
from components.java
groupId project.group
artifactId "${archivesBaseName}"
version System.getenv("CODE_VERSION") ?: "${version}"
}
}
}
task copyIdeaSettings(type: Copy) {
from "ide/idea"
into ".idea"
}
tasks.named('idea').configure {
dependsOn copyIdeaSettings
}
// Lets copy the distributions from build/install directory to /bin and /lib
// directories to be aligned with C* distribution format
task copyDist(type: Copy) {
from "$buildDir/install/$applicationName"
into "$projectDir"
}
task copyJolokia(type: Copy) {
from configurations.jolokia
into "$projectDir/src/main/dist/agents"
}
// Lets clean distribution directories along with default build directories.
clean.doLast {
["agents", "bin", "conf", "lib"].each {
println "Deleting directory $projectDir/$it"
delete "$projectDir/$it"
}
println "Deleting generated docs $projectDir/src/main/resources/docs"
delete "$projectDir/src/main/resources/docs"
}
test {
systemProperty "vertxweb.environment", "dev"
systemProperty "logback.configurationFile", "logback-sidecar.xml"
systemProperty "vertx.logger-delegate-factory-class-name", "io.vertx.core.logging.SLF4JLogDelegateFactory"
// ordinarily we don't need integration tests
// see the integrationTest task
useJUnitPlatform()
reports {
junitXml.enabled = true
def destDir = Paths.get(rootProject.rootDir.absolutePath, "build", "test-results", "test").toFile()
println("Destination directory for unit tests: ${destDir}")
junitXml.destination = destDir
html.enabled = true
}
testLogging {
events "passed", "skipped", "failed"
}
}
def JDK11_OPTIONS = ['-Djdk.attach.allowAttachSelf=true',
'--add-exports', 'java.base/jdk.internal.misc=ALL-UNNAMED',
'--add-exports', 'java.base/jdk.internal.ref=ALL-UNNAMED',
'--add-exports', 'java.base/sun.nio.ch=ALL-UNNAMED',
'--add-exports', 'java.management.rmi/com.sun.jmx.remote.internal.rmi=ALL-UNNAMED',
'--add-exports', 'java.rmi/sun.rmi.registry=ALL-UNNAMED',
'--add-exports', 'java.rmi/sun.rmi.server=ALL-UNNAMED',
'--add-exports', 'java.sql/java.sql=ALL-UNNAMED',
'--add-opens', 'java.base/java.lang.module=ALL-UNNAMED',
'--add-opens', 'java.base/jdk.internal.loader=ALL-UNNAMED',
'--add-opens', 'java.base/jdk.internal.ref=ALL-UNNAMED',
'--add-opens', 'java.base/jdk.internal.reflect=ALL-UNNAMED',
'--add-opens', 'java.base/jdk.internal.math=ALL-UNNAMED',
'--add-opens', 'java.base/jdk.internal.module=ALL-UNNAMED',
'--add-opens', 'java.base/jdk.internal.util.jar=ALL-UNNAMED',
'--add-opens', 'jdk.management/com.sun.management.internal=ALL-UNNAMED']
def integrationTest = task("integrationTest")
['integrationTestLightWeight', 'integrationTestHeavyWeight'].each { name ->
tasks.register(name, Test) {
if (JavaVersion.current().isJava11Compatible()) {
jvmArgs(JDK11_OPTIONS)
println("JVM arguments for $project.name are $allJvmArgs")
}
// Disable direct memory allocator as it doesn't release properly
systemProperty "cassandra.netty_use_heap_allocator", "true"
systemProperty "vertxweb.environment", "dev"
// config logback for in-jvm clusters
systemProperty "logback.configurationFile", "src/test/resources/logback-in-jvm-dtest.xml"
// Because tests are forked, we need to explicitly pass the system property from the
// Gradle JVM down to the children
def versionsToTest = System.getProperty("cassandra.sidecar.versions_to_test", null)
if (versionsToTest != "" && versionsToTest != null) {
systemProperty "cassandra.sidecar.versions_to_test", versionsToTest
}
useJUnitPlatform() {
if (name.contains("HeavyWeight"))
{
includeTags "heavy"
}
else
{
excludeTags "heavy"
}
}
reports {
junitXml.enabled = true
def destDir = Paths.get(rootProject.rootDir.absolutePath, "build", "test-results", "integration").toFile()
println("Destination directory for integration tests: ${destDir}")
junitXml.destination = destDir
html.enabled = true
}
testLogging {
events "passed", "skipped", "failed"
}
testClassesDirs = sourceSets.integrationTest.output.classesDirs
classpath = sourceSets.integrationTest.runtimeClasspath
shouldRunAfter test
forkEvery = 1 // DTest framework tends to have issues without forkEvery test class
maxHeapSize = integrationMaxHeapSize
maxParallelForks = integrationMaxParallelForks
afterTest { descriptor, result ->
def totalTime = (result.endTime - result.startTime) / 1000.0
logger.lifecycle("--")
if (totalTime >= 60) { // log the tests that take 1 minute and more
logger.warn("$descriptor.displayName took $totalTime s")
}
else {
logger.info("$descriptor.displayName took $totalTime s")
}
}
}
}
tasks.register("containerTest", Test) {
if (JavaVersion.current().isJava11Compatible()) {
jvmArgs(JDK11_OPTIONS)
println("JVM arguments for $project.name are $allJvmArgs")
}
useJUnitPlatform()
reports {
junitXml.enabled = true
def destDir = Paths.get(rootProject.rootDir.absolutePath, "build", "test-results", "containerTest").toFile()
println("Destination directory for testcontainer tests: ${destDir}")
junitXml.destination = destDir
html.enabled = true
}
testLogging {
events "passed", "skipped", "failed"
}
testClassesDirs = sourceSets.containerTest.output.classesDirs
classpath = sourceSets.containerTest.runtimeClasspath
shouldRunAfter test
}
// copy the user documentation to the final build
task copyDocs(type: Copy, dependsOn: ':docs:asciidoctor') {
from(tasks.getByPath(":docs:asciidoctor").outputs) {
include "**/*.html"
}
into "build/docs/"
exclude "tmp"
}
/**
* General configuration for linux packages.
* Can be overridden in the buildRpm and buildDeb configuration
* We can put dependencies here, such as java, but unfortunately since java is distributed
* in an inconsistent manner depending on the version you want (8 vs 11) we can't include Java
* as a requirement without the install breaking if you want to use a different version
*/
ospackage {
packageName = "cassandra-sidecar"
version = project.version
// ospackage puts packages into /opt/[package] by default
// which is _technically_ the right spot for packages
link("/usr/local/bin/cassandra-sidecar", "/opt/cassandra-sidecar/bin/cassandra-sidecar")
license "Apache License 2.0"
description "Sidecar Management Tool for Apache Cassandra"
os = LINUX
user "root"
}
buildRpm {
group = "build"
}
buildDeb {
group = "build"
}
applicationDistribution.from("LICENSE.txt") {
into ""
}
tasks.register('buildIgnoreRatList', Exec) {
description 'Builds a list of ignored files for the rat task from the unversioned git files'
commandLine 'bash', '-c', "git clean --force -d --dry-run -x | cut -c 14-"
doFirst {
standardOutput new FileOutputStream("${buildDir}/.rat-excludes.txt")
}
// allows task to fail when git/cut commands are unavailable or fail
ignoreExitValue = true
}
jacocoTestReport {
// include all jacoco execution data from different Test tasks, i.e. test, integration test, container test
executionData fileTree(project.buildDir).include("jacoco/*.exec")
}
rat {
doFirst {
def excludeFilePath = Paths.get("${buildDir}/.rat-excludes.txt")
def excludeLines = Files.readAllLines(excludeFilePath)
excludeLines.each { line ->
if (line.endsWith("/")) {
excludes.add("**/" + line + "**")
} else {
excludes.add(line)
}
}
}
// List of Gradle exclude directives, defaults to ['**/.gradle/**']
excludes.add("**/build/**")
excludes.add("CHANGES.txt")
// Documentation files
excludes.add("**/docs/src/**")
// gradle files
excludes.add("gradle/**")
excludes.add("gradlew")
excludes.add("gradlew.bat")
// resource files for test
excludes.add("**/test**/resources/**")
// XML, TXT and HTML reports directory, defaults to 'build/reports/rat'
reportDir.set(file("build/reports/rat"))
}
compileIntegrationTestJava.onlyIf { "true" != System.getenv("skipIntegrationTest") }
checkstyleIntegrationTest.onlyIf { "true" != System.getenv("skipIntegrationTest") }
spotbugsIntegrationTest.onlyIf { "true" != System.getenv("skipIntegrationTest") }
compileContainerTestJava.onlyIf { "true" != System.getenv("skipContainerTest") }
checkstyleContainerTest.onlyIf { "true" != System.getenv("skipContainerTest") }
spotbugsContainerTest.onlyIf { "true" != System.getenv("skipContainerTest") }
// copyDist gets called on every build
copyDist.dependsOn installDist, copyJolokia
integrationTest.dependsOn integrationTestLightWeight, integrationTestHeavyWeight
check.dependsOn codeCheckTasks, containerTest, integrationTest, jacocoTestReport
build.dependsOn copyDist, copyJolokia, copyDocs
run.dependsOn build
tasks.named('rat').configure {
dependsOn(buildIgnoreRatList)
}