Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make open api tasks compatible with configuration cache #450

Merged
merged 19 commits into from
Sep 10, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
199 changes: 99 additions & 100 deletions build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -64,12 +64,12 @@ tasks.jar {
manifest.attributes(
"Built-JDK" to System.getProperty("java.version"),
"Implementation-Title" to "MQTT CLI",
"Implementation-Version" to project.version,
"Implementation-Version" to provider { project.version.toString() },
"Implementation-Vendor" to "HiveMQ GmbH",
"Specification-Title" to "MQTT CLI",
"Specification-Version" to project.version,
"Specification-Version" to provider { project.version.toString() },
"Specification-Vendor" to "HiveMQ GmbH",
"Main-Class" to application.mainClass.get(),
"Main-Class" to application.mainClass,
"Built-Date" to SimpleDateFormat("yyyy-MM-dd").format(Date()),
)
}
Expand Down Expand Up @@ -159,51 +159,52 @@ dependencies {
}

val generateHivemqOpenApi by tasks.registering(GenerateTask::class) {
group = "hivemq"
group = "openapi"
generatorName = "java"
inputSpec = hivemqOpenApi.singleFile.path
outputDir = layout.buildDirectory.dir("tmp/$name").get().asFile.absolutePath
inputSpec = hivemqOpenApi.elements.map { it.single().asFile.path }
val outputDir = layout.buildDirectory.dir("tmp/$name")
this.outputDir = outputDir.map { it.asFile.absolutePath }
cleanupOutput = true

apiPackage = "com.hivemq.cli.openapi.hivemq"
modelPackage = "com.hivemq.cli.openapi.hivemq"
configOptions.put("dateLibrary", "java8")
modelNamePrefix = "HivemqOpenapi"
configOptions.put("hideGenerationTimestamp", "true")
configOptions.put("openApiNullable", "false")

inputs.file(hivemqOpenApi.elements.map { it.first() }).withPropertyName("inputSpec")
.withPathSensitivity(PathSensitivity.NONE)
val outputSrcDir = layout.buildDirectory.dir("generated/openapi/hivemq/java")
outputs.dir(outputSrcDir).withPropertyName("outputSrcDir")
outputs.cacheIf { true }
doFirst { delete(outputDir) }

doLast {
sync {
from("${outputDir.get()}/src/main/java")
into(outputSrcDir)
}
outputSrcDir.get().asFile.deleteRecursively()
outputDir.get().asFile.resolve("src/main/java").copyRecursively(outputSrcDir.get().asFile)
outputDir.get().asFile.deleteRecursively()
}
}

val generateSwarmOpenApi by tasks.registering(GenerateTask::class) {
group = "swarm"
group = "openapi"
generatorName = "java"
inputSpec = swarmOpenApi.singleFile.path
outputDir = layout.buildDirectory.dir("tmp/$name").get().asFile.absolutePath
inputSpec = swarmOpenApi.elements.map { it.single().asFile.path }
val outputDir = layout.buildDirectory.dir("tmp/$name")
this.outputDir = outputDir.map { it.asFile.absolutePath }
cleanupOutput = true

apiPackage = "com.hivemq.cli.openapi.swarm"
modelPackage = "com.hivemq.cli.openapi.swarm"
configOptions.put("dateLibrary", "java8")
configOptions.put("hideGenerationTimestamp", "true")
configOptions.put("openApiNullable", "false")

inputs.file(swarmOpenApi.elements.map { it.first() }).withPropertyName("inputSpec")
.withPathSensitivity(PathSensitivity.NONE)
val outputSrcDir = layout.buildDirectory.dir("generated/openapi/swarm/java")
outputs.dir(outputSrcDir).withPropertyName("outputSrcDir")
outputs.cacheIf { true }
doFirst { delete(outputDir) }

doLast {
sync {
from("${outputDir.get()}/src/main/java")
into(outputSrcDir)
include("${apiPackage.get().replace('.', '/')}/**")
}
outputSrcDir.get().asFile.deleteRecursively()
val path = apiPackage.get().replace('.', '/')
outputDir.get().asFile.resolve("src/main/java/$path").copyRecursively(outputSrcDir.get().asFile.resolve(path))
outputDir.get().asFile.deleteRecursively()
}
}

Expand Down Expand Up @@ -257,30 +258,35 @@ testing {
implementation(project())
}

ociImageDependencies {
runtime("hivemq:hivemq4:latest") { isChanging = true }
runtime("hivemq:hivemq-swarm:latest") { isChanging = true }
oci.of(this) {
imageDependencies {
runtime("hivemq:hivemq4:latest") { isChanging = true }
runtime("hivemq:hivemq-swarm:latest") { isChanging = true }
}
val linuxAmd64 = platformSelector(platform("linux", "amd64"))
val linuxArm64v8 = platformSelector(platform("linux", "arm64", "v8"))
platformSelector = if (System.getenv("CI_RUN") != null) linuxAmd64 else linuxAmd64.and(linuxArm64v8)
}
}

val systemTest by registering(JvmTestSuite::class) {
testType = TestSuiteType.FUNCTIONAL_TEST
targets {
all {
testTask.configure {
testTask {
systemProperties["junit.jupiter.testinstance.lifecycle.default"] = "per_class"
}
}
named("systemTest") {
testTask.configure {
testTask {
dependsOn(tasks.shadowJar)
systemProperties["cliExec"] = "${javaLauncher.get().executablePath.asFile.absolutePath} -jar ${
tasks.shadowJar.get().archiveFile.get()
}"
}
}
register("systemTestNative") {
testTask.configure {
testTask {
dependsOn(tasks.nativeCompile)
systemProperties["cliExec"] = tasks.nativeCompile.get().outputFile.get().toString()
}
Expand All @@ -301,34 +307,22 @@ testing {
implementation(libs.hivemq.mqttClient)
}

ociImageDependencies {
runtime(project).tag("latest")
oci.of(this) {
imageDependencies {
runtime(project).tag("latest")
}
val linuxAmd64 = platformSelector(platform("linux", "amd64"))
val linuxArm64v8 = platformSelector(platform("linux", "arm64", "v8"))
platformSelector = if (System.getenv("CI_RUN") != null) linuxAmd64 else linuxAmd64.and(linuxArm64v8)
}
}

tasks.named("check") {
dependsOn(integrationTest, systemTest)
}

tasks.named("integrationTestOciRegistryData", oci.imagesTaskClass) {
val linuxAmd64 = oci.platformSelector(oci.platform("linux", "amd64"))
val linuxArm64v8 = oci.platformSelector(oci.platform("linux", "arm64", "v8"))
platformSelector = if (System.getenv("CI_RUN") != null) {
linuxAmd64
} else {
linuxAmd64.and(linuxArm64v8)
}
}
}
}

dependencies {
modules {
module("org.bouncycastle:bcpkix-jdk15on") { replacedBy("org.bouncycastle:bcpkix-jdk18on") }
module("org.bouncycastle:bcprov-jdk15on") { replacedBy("org.bouncycastle:bcprov-jdk18on") }
module("org.bouncycastle:bcutil-jdk15on") { replacedBy("org.bouncycastle:bcutil-jdk18on") }
}
}

/* ******************** compliance ******************** */

Expand Down Expand Up @@ -485,16 +479,29 @@ val buildBrewZip by tasks.registering(Zip::class) {
}
}

val buildBrewFormula by tasks.registering(Sync::class) {
dependsOn(buildBrewZip)

from("packages/homebrew/mqtt-cli.rb")
into(layout.buildDirectory.dir("packages/homebrew/formula"))
filter {
it.replace("@@description@@", project.description!!) //
.replace("@@version@@", project.version.toString())
.replace("@@filename@@", buildBrewZip.get().archiveFileName.get())
.replace("@@shasum@@", sha256Hash(buildBrewZip.get().archiveFile.get().asFile))
val buildBrewFormula by tasks.registering {
val inputFile = layout.projectDirectory.file("packages/homebrew/mqtt-cli.rb")
inputs.file(inputFile).withPropertyName("inputFile").withPathSensitivity(PathSensitivity.NONE)
val description = provider { project.description!! }
inputs.property("description", description)
val version = provider { project.version.toString() }
inputs.property("version", version)
val archiveFileName = buildBrewZip.flatMap { it.archiveFileName }
inputs.property("archiveFileName", archiveFileName)
val archiveFile = buildBrewZip.flatMap { it.archiveFile }
inputs.file(archiveFile).withPropertyName("archiveFile").withPathSensitivity(PathSensitivity.NONE)
val outputFile = layout.buildDirectory.file("packages/homebrew/mqtt-cli.rb")
outputs.file(outputFile).withPropertyName("outputFile")
doLast {
val archiveBytes = archiveFile.get().asFile.readBytes()
val archiveDigest = MessageDigest.getInstance("SHA-256").digest(archiveBytes)
val archiveChecksum = archiveDigest.fold("") { string, b -> string + "%02x".format(b) }
val content = inputFile.asFile.readText() //
.replace("@@description@@", description.get()) //
.replace("@@version@@", version.get()) //
.replace("@@filename@@", archiveFileName.get()) //
.replace("@@shasum@@", archiveChecksum)
outputFile.get().asFile.writeText(content)
}
}

Expand All @@ -517,20 +524,20 @@ ospackage {
user = "root"
permissionGroup = "root"

into("/opt/$packageName")
val destinationPath = "/opt/$packageName"
into(destinationPath)
from(tasks.shadowJar)
val jarFileName = tasks.shadowJar.flatMap { it.archiveFileName }
from("packages/linux/mqtt", closureOf<CopySpec> {
fileMode = 0b111_101_101 // 0755
filter {
it.replace("@@jarPath@@", "/opt/$packageName/${tasks.shadowJar.get().archiveFileName.get()}")
}
filter { it.replace("@@jarPath@@", "$destinationPath/${jarFileName.get()}") }
})
from("LICENSE", closureOf<CopySpec> {
into("licenses")
CopySpecEnhancement.fileType(this, Directive.LICENSE)
})

link("/usr/bin/mqtt", "/opt/$packageName/mqtt", 0b111_101_101)
link("/usr/bin/mqtt", "$destinationPath/mqtt", 0b111_101_101)
}

tasks.buildDeb {
Expand All @@ -542,42 +549,50 @@ tasks.buildRpm {
requires("jre", "1.8.0", Flags.GREATER or Flags.EQUAL)
}

val buildDebianPackage by tasks.registering(Copy::class) {
from(tasks.buildDeb.flatMap { it.archiveFile })
into(layout.buildDirectory.dir("packages/debian"))
rename { "${project.name}-${project.version}.deb" }
val buildDebianPackage by tasks.registering {
val inputFile = tasks.buildDeb.flatMap { it.archiveFile }
inputs.file(inputFile).withPropertyName("inputFile").withPathSensitivity(PathSensitivity.NONE)
val outputFile = layout.buildDirectory.file(provider { "packages/debian/${project.name}-${project.version}.deb" })
outputs.file(outputFile).withPropertyName("outputFile")
doLast {
inputFile.get().asFile.copyTo(outputFile.get().asFile, true)
}
}

val buildRpmPackage by tasks.registering(Copy::class) {
from(tasks.buildRpm.flatMap { it.archiveFile })
into(layout.buildDirectory.dir("packages/rpm"))
rename { "${project.name}-${project.version}.rpm" }
val buildRpmPackage by tasks.registering {
val inputFile = tasks.buildRpm.flatMap { it.archiveFile }
inputs.file(inputFile).withPropertyName("inputFile").withPathSensitivity(PathSensitivity.NONE)
val outputFile = layout.buildDirectory.file(provider { "packages/rpm/${project.name}-${project.version}.rpm" })
outputs.file(outputFile).withPropertyName("outputFile")
doLast {
inputFile.get().asFile.copyTo(outputFile.get().asFile, true)
}
}

/* ******************** windows zip ******************** */

launch4j {
headerType = "console"
mainClassName = application.mainClass.get()
mainClassName = application.mainClass
icon = "$projectDir/icons/05-mqtt-cli-icon.ico"
setJarTask(tasks.shadowJar.get())
setJarTask(tasks.shadowJar.map { it })
copyConfigurable = emptyList<Any>()
copyright = "Copyright 2019-present HiveMQ and the HiveMQ Community"
companyName = "HiveMQ GmbH"
downloadUrl = "https://openjdk.java.net/install/"
jreMinVersion = "1.8"
windowTitle = "MQTT CLI"
version = project.version.toString()
textVersion = project.version.toString()
version = provider { project.version.toString() }
textVersion = provider { project.version.toString() }
}

val buildWindowsZip by tasks.registering(Zip::class) {

archiveClassifier = "win"
destinationDirectory = layout.buildDirectory.dir("packages/windows")

val exeFileName = launch4j.outfile
from("packages/windows") {
filter { it.replace("@@exeName@@", launch4j.outfile.get()) }
filter { it.replace("@@exeName@@", exeFileName.get()) }
}
from(tasks.createExe.map { it.dest })
from("LICENSE")
Expand All @@ -589,18 +604,11 @@ val buildPackages by tasks.registering {
dependsOn(buildBrewFormula, buildDebianPackage, buildRpmPackage, buildWindowsZip)
}

/* ******************** Publish Draft-Release with all packages to GitHub Releases ******************** */
/* ******************** Attach all packages to GitHub release ******************** */

githubRelease {
token(System.getenv("githubToken"))
draft = true
releaseAssets(
tasks.shadowJar,
buildBrewZip,
buildDebianPackage.map { fileTree(it.destinationDir) },
buildRpmPackage.map { fileTree(it.destinationDir) },
buildWindowsZip,
)
releaseAssets(tasks.shadowJar, buildBrewZip, buildDebianPackage, buildRpmPackage, buildWindowsZip)
allowUploadToExisting = true
}

Expand All @@ -623,8 +631,8 @@ oci {
}
imageDefinitions.register("main") {
allPlatforms {
parentImages {
add("library:eclipse-temurin:sha256!e2318d304bc50c798edea630a23f7b90b1adb14a02658de91d2c99027a071c26") // 21.0.3_9-jre-jammy
dependencies {
runtime("library:eclipse-temurin:sha256!ea878d7ef79653c16f6bfdfbd3bf20ae80f4f645f66339e9153ae0d481385225") // 21.0.4_7-jre-jammy
}
config {
entryPoint.add("java")
Expand Down Expand Up @@ -687,15 +695,6 @@ val updateVersionInFiles by tasks.registering {
}
}

/* ******************** helpers ******************** */

fun sha256Hash(file: File): String {
val bytes = file.readBytes()
val md = MessageDigest.getInstance("SHA-256")
val digest = md.digest(bytes)
return digest.fold("") { str, it -> str + "%02x".format(it) }
}

/* ******************** artifacts ******************** */

val releaseBinary: Configuration by configurations.creating {
Expand Down
10 changes: 5 additions & 5 deletions gradle/libs.versions.toml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ awaitility = "4.2.2"
bouncycastle = "1.78.1"
dagger = "2.52"
graalvm-nativeImage-svm = "24.0.2"
gradleOci-junitJupiter = "0.5.0"
gradleOci-junitJupiter = "0.6.0"
gson = "2.11.0"
gsonFire = "1.9.0"
guava = "33.3.0-jre"
Expand All @@ -26,7 +26,7 @@ netty = "4.1.113.Final"
okhttp = "4.12.0"
openCsv = "5.9"
picocli = "4.7.6"
swagger-annotations = "1.6.14"
swagger-annotations = "2.2.22"
testcontainers = "1.20.1"
tinylog = "2.7.0"

Expand Down Expand Up @@ -67,7 +67,7 @@ openCsv = { module = "com.opencsv:opencsv", version.ref = "openCsv" }
picocli = { module = "info.picocli:picocli", version.ref = "picocli" }
picocli-codegen = { module = "info.picocli:picocli-codegen", version.ref = "picocli" }
picocli-shellJline = { module = "info.picocli:picocli-shell-jline3", version.ref = "picocli" }
swagger-annotations = { module = "io.swagger:swagger-annotations", version.ref = "swagger-annotations" }
swagger-annotations = { module = "io.swagger.core.v3:swagger-annotations", version.ref = "swagger-annotations" }
testcontainers = { module = "org.testcontainers:testcontainers", version.ref = "testcontainers" }
testcontainers-hivemq = { module = "org.testcontainers:hivemq", version.ref = "testcontainers" }
testcontainers-junitJupiter = { module = "org.testcontainers:junit-jupiter", version.ref = "testcontainers" }
Expand All @@ -83,6 +83,6 @@ graalvm-native = { id = "org.graalvm.buildtools.native", version = "0.10.2" }
launch4j = { id = "edu.sc.seis.launch4j", version = "3.0.6" }
license = { id = "com.github.hierynomus.license", version = "0.16.1" }
nebula-ospackage = { id = "com.netflix.nebula.ospackage", version = "11.10.0" }
oci = { id = "io.github.sgtsilvio.gradle.oci", version = "0.15.1" }
openapi-generator = { id = "org.openapi.generator", version = "4.3.1" } # >= 5.0.0 breaks the tasks
oci = { id = "io.github.sgtsilvio.gradle.oci", version = "0.16.0" }
openapi-generator = { id = "org.openapi.generator", version = "7.8.0" }
shadow = { id = "com.github.johnrengelman.shadow", version = "8.1.1" }
Loading
Loading