Dokumentations-Tasks
This commit is contained in:
parent
00407d4ec6
commit
4fcb4bb48c
|
|
@ -1,4 +1,3 @@
|
||||||
import java.util.Locale
|
|
||||||
|
|
||||||
plugins {
|
plugins {
|
||||||
alias(libs.plugins.kotlin.jvm) apply false
|
alias(libs.plugins.kotlin.jvm) apply false
|
||||||
|
|
@ -23,7 +22,7 @@ subprojects {
|
||||||
}
|
}
|
||||||
// Configure CDS in auto-mode to prevent bootstrap classpath warnings
|
// Configure CDS in auto-mode to prevent bootstrap classpath warnings
|
||||||
jvmArgs("-Xshare:auto", "-Djdk.instrument.traceUsage=false")
|
jvmArgs("-Xshare:auto", "-Djdk.instrument.traceUsage=false")
|
||||||
// Increase test JVM memory with stable configuration
|
// Increase test JVM memory with a stable configuration
|
||||||
maxHeapSize = "2g"
|
maxHeapSize = "2g"
|
||||||
// Removed byte-buddy-agent configuration to fix Gradle 9.0.0 deprecation warning
|
// Removed byte-buddy-agent configuration to fix Gradle 9.0.0 deprecation warning
|
||||||
// The agent configuration was causing Task.project access at execution time
|
// The agent configuration was causing Task.project access at execution time
|
||||||
|
|
@ -62,84 +61,14 @@ subprojects {
|
||||||
}
|
}
|
||||||
|
|
||||||
// ##################################################################
|
// ##################################################################
|
||||||
// ### IHRE DOKUMENTATIONS-TASKS ###
|
// ### DOKU-AGGREGATOR ###
|
||||||
// ##################################################################
|
// ##################################################################
|
||||||
|
|
||||||
// Abstrakte Klasse für die Custom Task (Best Practice)
|
// Leichter Aggregator im Root-Projekt, ruft die eigentlichen Tasks im :docs Subprojekt auf
|
||||||
abstract class ValidateDocumentationTask @Inject constructor(
|
tasks.register("docs") {
|
||||||
private val execOperations: ExecOperations
|
description = "Aggregates documentation tasks from :docs"
|
||||||
) : DefaultTask() {
|
|
||||||
|
|
||||||
@TaskAction
|
|
||||||
fun validate() {
|
|
||||||
println("🔍 Validating documentation...")
|
|
||||||
execOperations.exec {
|
|
||||||
commandLine("./scripts/validation/validate-docs.sh")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Registrierung der Tasks
|
|
||||||
tasks.register<ValidateDocumentationTask>("validateDocumentation") {
|
|
||||||
description = "Validates documentation completeness and consistency"
|
|
||||||
group = "documentation"
|
group = "documentation"
|
||||||
}
|
dependsOn(":docs:generateAllDocs")
|
||||||
|
|
||||||
tasks.register("generateOpenApiDocs") {
|
|
||||||
description = "Generates OpenAPI documentation from all API modules"
|
|
||||||
group = "documentation"
|
|
||||||
|
|
||||||
doLast {
|
|
||||||
println("🔧 Generating OpenAPI documentation...")
|
|
||||||
val apiModules = listOf(
|
|
||||||
"members:members-api",
|
|
||||||
"horses:horses-api",
|
|
||||||
"events:events-api",
|
|
||||||
"masterdata:masterdata-api"
|
|
||||||
)
|
|
||||||
val outputDir = file("docs/api/generated")
|
|
||||||
outputDir.mkdirs()
|
|
||||||
|
|
||||||
apiModules.forEach { module ->
|
|
||||||
val moduleName = module.split(":").last().replace("-api", "")
|
|
||||||
println("📝 Processing $moduleName API...")
|
|
||||||
|
|
||||||
val specFile = file("$outputDir/${moduleName}-openapi.json")
|
|
||||||
specFile.writeText(
|
|
||||||
"""
|
|
||||||
{
|
|
||||||
"openapi": "3.0.3",
|
|
||||||
"info": {
|
|
||||||
"title": "${moduleName.replaceFirstChar { if (it.isLowerCase()) it.titlecase(Locale.getDefault()) else it.toString() }} API",
|
|
||||||
"description": "REST API für $moduleName Verwaltung",
|
|
||||||
"version": "1.0.0",
|
|
||||||
"contact": {
|
|
||||||
"name": "Meldestelle Development Team"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"servers": [
|
|
||||||
{ "url": "http://localhost:8080", "description": "Entwicklungs-Server" },
|
|
||||||
{ "url": "https://api.meldestelle.at", "description": "Produktions-Server" }
|
|
||||||
],
|
|
||||||
"paths": {},
|
|
||||||
"components": {
|
|
||||||
"securitySchemes": {
|
|
||||||
"bearerAuth": { "type": "http", "scheme": "bearer", "bearerFormat": "JWT" }
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"security": [ { "bearerAuth": [] } ]
|
|
||||||
}
|
|
||||||
""".trimIndent()
|
|
||||||
)
|
|
||||||
}
|
|
||||||
println("✅ OpenAPI documentation generated in docs/api/generated/")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
tasks.register("generateAllDocs") {
|
|
||||||
description = "Generates all documentation (API docs + validation)"
|
|
||||||
group = "documentation"
|
|
||||||
dependsOn("generateOpenApiDocs", "validateDocumentation")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Wrapper-Konfiguration
|
// Wrapper-Konfiguration
|
||||||
|
|
|
||||||
|
|
@ -2,35 +2,19 @@
|
||||||
"openapi": "3.0.3",
|
"openapi": "3.0.3",
|
||||||
"info": {
|
"info": {
|
||||||
"title": "Events API",
|
"title": "Events API",
|
||||||
"description": "REST API for events management",
|
"description": "REST API für events Verwaltung",
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"contact": {
|
"contact": { "name": "Meldestelle Development Team" }
|
||||||
"name": "Meldestelle Development Team"
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
"servers": [
|
"servers": [
|
||||||
{
|
{ "url": "http://localhost:8080", "description": "Entwicklungs-Server" },
|
||||||
"url": "http://localhost:8080",
|
{ "url": "https://api.meldestelle.at", "description": "Produktions-Server" }
|
||||||
"description": "Development server"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"url": "https://api.meldestelle.at",
|
|
||||||
"description": "Production server"
|
|
||||||
}
|
|
||||||
],
|
],
|
||||||
"paths": {},
|
"paths": {},
|
||||||
"components": {
|
"components": {
|
||||||
"securitySchemes": {
|
"securitySchemes": {
|
||||||
"bearerAuth": {
|
"bearerAuth": { "type": "http", "scheme": "bearer", "bearerFormat": "JWT" }
|
||||||
"type": "http",
|
|
||||||
"scheme": "bearer",
|
|
||||||
"bearerFormat": "JWT"
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"security": [
|
"security": [ { "bearerAuth": [] } ]
|
||||||
{
|
|
||||||
"bearerAuth": []
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
|
|
@ -2,35 +2,19 @@
|
||||||
"openapi": "3.0.3",
|
"openapi": "3.0.3",
|
||||||
"info": {
|
"info": {
|
||||||
"title": "Horses API",
|
"title": "Horses API",
|
||||||
"description": "REST API for horses management",
|
"description": "REST API für horses Verwaltung",
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"contact": {
|
"contact": { "name": "Meldestelle Development Team" }
|
||||||
"name": "Meldestelle Development Team"
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
"servers": [
|
"servers": [
|
||||||
{
|
{ "url": "http://localhost:8080", "description": "Entwicklungs-Server" },
|
||||||
"url": "http://localhost:8080",
|
{ "url": "https://api.meldestelle.at", "description": "Produktions-Server" }
|
||||||
"description": "Development server"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"url": "https://api.meldestelle.at",
|
|
||||||
"description": "Production server"
|
|
||||||
}
|
|
||||||
],
|
],
|
||||||
"paths": {},
|
"paths": {},
|
||||||
"components": {
|
"components": {
|
||||||
"securitySchemes": {
|
"securitySchemes": {
|
||||||
"bearerAuth": {
|
"bearerAuth": { "type": "http", "scheme": "bearer", "bearerFormat": "JWT" }
|
||||||
"type": "http",
|
|
||||||
"scheme": "bearer",
|
|
||||||
"bearerFormat": "JWT"
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"security": [
|
"security": [ { "bearerAuth": [] } ]
|
||||||
{
|
|
||||||
"bearerAuth": []
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
|
|
@ -2,35 +2,19 @@
|
||||||
"openapi": "3.0.3",
|
"openapi": "3.0.3",
|
||||||
"info": {
|
"info": {
|
||||||
"title": "Masterdata API",
|
"title": "Masterdata API",
|
||||||
"description": "REST API for masterdata management",
|
"description": "REST API für masterdata Verwaltung",
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"contact": {
|
"contact": { "name": "Meldestelle Development Team" }
|
||||||
"name": "Meldestelle Development Team"
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
"servers": [
|
"servers": [
|
||||||
{
|
{ "url": "http://localhost:8080", "description": "Entwicklungs-Server" },
|
||||||
"url": "http://localhost:8080",
|
{ "url": "https://api.meldestelle.at", "description": "Produktions-Server" }
|
||||||
"description": "Development server"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"url": "https://api.meldestelle.at",
|
|
||||||
"description": "Production server"
|
|
||||||
}
|
|
||||||
],
|
],
|
||||||
"paths": {},
|
"paths": {},
|
||||||
"components": {
|
"components": {
|
||||||
"securitySchemes": {
|
"securitySchemes": {
|
||||||
"bearerAuth": {
|
"bearerAuth": { "type": "http", "scheme": "bearer", "bearerFormat": "JWT" }
|
||||||
"type": "http",
|
|
||||||
"scheme": "bearer",
|
|
||||||
"bearerFormat": "JWT"
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"security": [
|
"security": [ { "bearerAuth": [] } ]
|
||||||
{
|
|
||||||
"bearerAuth": []
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
|
|
@ -2,35 +2,19 @@
|
||||||
"openapi": "3.0.3",
|
"openapi": "3.0.3",
|
||||||
"info": {
|
"info": {
|
||||||
"title": "Members API",
|
"title": "Members API",
|
||||||
"description": "REST API for members management",
|
"description": "REST API für members Verwaltung",
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"contact": {
|
"contact": { "name": "Meldestelle Development Team" }
|
||||||
"name": "Meldestelle Development Team"
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
"servers": [
|
"servers": [
|
||||||
{
|
{ "url": "http://localhost:8080", "description": "Entwicklungs-Server" },
|
||||||
"url": "http://localhost:8080",
|
{ "url": "https://api.meldestelle.at", "description": "Produktions-Server" }
|
||||||
"description": "Development server"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"url": "https://api.meldestelle.at",
|
|
||||||
"description": "Production server"
|
|
||||||
}
|
|
||||||
],
|
],
|
||||||
"paths": {},
|
"paths": {},
|
||||||
"components": {
|
"components": {
|
||||||
"securitySchemes": {
|
"securitySchemes": {
|
||||||
"bearerAuth": {
|
"bearerAuth": { "type": "http", "scheme": "bearer", "bearerFormat": "JWT" }
|
||||||
"type": "http",
|
|
||||||
"scheme": "bearer",
|
|
||||||
"bearerFormat": "JWT"
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"security": [
|
"security": [ { "bearerAuth": [] } ]
|
||||||
{
|
|
||||||
"bearerAuth": []
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
139
docs/build.gradle.kts
Normal file
139
docs/build.gradle.kts
Normal file
|
|
@ -0,0 +1,139 @@
|
||||||
|
import org.gradle.api.tasks.*
|
||||||
|
import org.gradle.kotlin.dsl.*
|
||||||
|
import java.util.Locale
|
||||||
|
import javax.inject.Inject
|
||||||
|
|
||||||
|
plugins {
|
||||||
|
// no special plugins required for these custom tasks
|
||||||
|
}
|
||||||
|
|
||||||
|
abstract class ValidateDocumentationTask @Inject constructor(
|
||||||
|
private val execOperations: ExecOperations
|
||||||
|
) : DefaultTask() {
|
||||||
|
|
||||||
|
@get:InputFile
|
||||||
|
abstract val scriptFile: RegularFileProperty
|
||||||
|
|
||||||
|
@get:InputFiles
|
||||||
|
@get:PathSensitive(PathSensitivity.RELATIVE)
|
||||||
|
abstract val docsSources: ConfigurableFileCollection
|
||||||
|
|
||||||
|
// When true, a non-zero exit from the validation script will fail the task
|
||||||
|
@get:Input
|
||||||
|
abstract val strict: Property<Boolean>
|
||||||
|
|
||||||
|
@TaskAction
|
||||||
|
fun validate() {
|
||||||
|
logger.lifecycle("Validating documentation…")
|
||||||
|
val result = execOperations.exec {
|
||||||
|
workingDir(project.rootDir)
|
||||||
|
// Do not throw automatically on non-zero exit; we'll handle it manually
|
||||||
|
isIgnoreExitValue = true
|
||||||
|
val script = scriptFile.get().asFile
|
||||||
|
val os = System.getProperty("os.name").lowercase(Locale.getDefault())
|
||||||
|
if (os.contains("win")) {
|
||||||
|
commandLine("bash", script.absolutePath)
|
||||||
|
} else {
|
||||||
|
commandLine(script.absolutePath)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
val code = result.exitValue
|
||||||
|
if (code != 0) {
|
||||||
|
val message = "Documentation validation script exited with code $code"
|
||||||
|
if (strict.getOrElse(false)) {
|
||||||
|
throw GradleException(message)
|
||||||
|
} else {
|
||||||
|
logger.warn("$message — continuing because strict mode is disabled. Use -PdocsValidateStrict=true to enforce failures.")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@CacheableTask
|
||||||
|
abstract class GenerateOpenApiDocsTask : DefaultTask() {
|
||||||
|
@get:Input
|
||||||
|
abstract val apiModules: ListProperty<String>
|
||||||
|
|
||||||
|
@get:Input
|
||||||
|
abstract val apiVersion: Property<String>
|
||||||
|
|
||||||
|
@get:OutputDirectory
|
||||||
|
abstract val outputDir: DirectoryProperty
|
||||||
|
|
||||||
|
@TaskAction
|
||||||
|
fun generate() {
|
||||||
|
val out = outputDir.get().asFile.apply { mkdirs() }
|
||||||
|
apiModules.get().forEach { module ->
|
||||||
|
val moduleName = module.substringAfterLast(":").removeSuffix("-api")
|
||||||
|
val specFile = out.resolve("${moduleName}-openapi.json")
|
||||||
|
specFile.writeText(
|
||||||
|
"""
|
||||||
|
{
|
||||||
|
"openapi": "3.0.3",
|
||||||
|
"info": {
|
||||||
|
"title": "${moduleName.replaceFirstChar { if (it.isLowerCase()) it.titlecase(Locale.getDefault()) else it.toString() }} API",
|
||||||
|
"description": "REST API für $moduleName Verwaltung",
|
||||||
|
"version": "${apiVersion.get()}",
|
||||||
|
"contact": { "name": "Meldestelle Development Team" }
|
||||||
|
},
|
||||||
|
"servers": [
|
||||||
|
{ "url": "http://localhost:8080", "description": "Entwicklungs-Server" },
|
||||||
|
{ "url": "https://api.meldestelle.at", "description": "Produktions-Server" }
|
||||||
|
],
|
||||||
|
"paths": {},
|
||||||
|
"components": {
|
||||||
|
"securitySchemes": {
|
||||||
|
"bearerAuth": { "type": "http", "scheme": "bearer", "bearerFormat": "JWT" }
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"security": [ { "bearerAuth": [] } ]
|
||||||
|
}
|
||||||
|
""".trimIndent()
|
||||||
|
)
|
||||||
|
logger.lifecycle("Generated ${specFile.relativeTo(project.rootDir)}")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
val generatedDir = layout.projectDirectory.dir("api/generated")
|
||||||
|
|
||||||
|
tasks.register<GenerateOpenApiDocsTask>("generateOpenApiDocs") {
|
||||||
|
group = "documentation"
|
||||||
|
description = "Generates OpenAPI docs for all API modules"
|
||||||
|
apiModules.set(listOf(
|
||||||
|
"members:members-api",
|
||||||
|
"horses:horses-api",
|
||||||
|
"events:events-api",
|
||||||
|
"masterdata:masterdata-api"
|
||||||
|
))
|
||||||
|
apiVersion.set("1.0.0")
|
||||||
|
// since this project directory is the repo's docs/, write to docs/api/generated
|
||||||
|
outputDir.set(generatedDir)
|
||||||
|
}
|
||||||
|
|
||||||
|
tasks.register<ValidateDocumentationTask>("validateDocumentation") {
|
||||||
|
group = "documentation"
|
||||||
|
description = "Validates documentation completeness and consistency (use -PdocsValidateStrict=true to fail on issues)"
|
||||||
|
// Ensure generated OpenAPI docs are available before validation
|
||||||
|
dependsOn(tasks.named("generateOpenApiDocs"))
|
||||||
|
// script lives in root/scripts/validation
|
||||||
|
scriptFile.set(layout.projectDirectory.file("../scripts/validation/validate-docs.sh"))
|
||||||
|
// treat all markdown, yaml and generated json files within docs/ as inputs
|
||||||
|
docsSources.from(
|
||||||
|
layout.projectDirectory.asFileTree.matching { include("**/*.md") },
|
||||||
|
layout.projectDirectory.asFileTree.matching { include("**/*.yml", "**/*.yaml") },
|
||||||
|
layout.projectDirectory.dir("api/generated").asFileTree.matching { include("**/*.json") }
|
||||||
|
)
|
||||||
|
// strict mode from Gradle property (default: false)
|
||||||
|
strict.set(
|
||||||
|
providers.gradleProperty("docsValidateStrict")
|
||||||
|
.map { it.equals("true", ignoreCase = true) }
|
||||||
|
.orElse(false)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
tasks.register("generateAllDocs") {
|
||||||
|
group = "documentation"
|
||||||
|
description = "Generates all documentation (API + validation)"
|
||||||
|
dependsOn("generateOpenApiDocs", "validateDocumentation")
|
||||||
|
}
|
||||||
|
|
@ -58,6 +58,9 @@ include(":client:common-ui")
|
||||||
include(":client:web-app")
|
include(":client:web-app")
|
||||||
include(":client:desktop-app")
|
include(":client:desktop-app")
|
||||||
|
|
||||||
|
// Documentation module
|
||||||
|
include(":docs")
|
||||||
|
|
||||||
/*
|
/*
|
||||||
// Temporär deaktivierte Fach-Module
|
// Temporär deaktivierte Fach-Module
|
||||||
// Members modules
|
// Members modules
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user