- Multi-stage Docker build: Dockerfile compiles frontend (Node.js) and backend (Gradle) inside Docker; no local Java/Node.js required - Security hardening: replaced full host root mount with specific directory mounts (/proc, /sys, /etc, /var, /home, /opt, /tmp, /srv, /usr) - Host metrics consistency: LinuxMemoryService and CpuDetailsService now read from /host/proc instead of container OSHI - Concurrency: replaced synchronized with AtomicReference in 3 services - Global error handling: added @RestControllerAdvice for JSON error responses - Unit tests: added 32 tests for /proc parsers, CPU usage, process uptime - Docker security: non-root user, read-only FS, no-new-privileges, healthcheck - Debug logging: added log.debug() in silent catch blocks - Documentation: updated README, INSTALLATION, DEVELOPMENT, CONFIGURATION, ARCHITECTURE, CHANGELOG Co-authored-by: Junie <junie@jetbrains.com>
90 lines
2.3 KiB
Groovy
90 lines
2.3 KiB
Groovy
plugins {
|
|
id 'java'
|
|
id 'org.springframework.boot' version '4.1.2'
|
|
id 'io.spring.dependency-management' version '1.1.7'
|
|
}
|
|
|
|
group = 'com.htop-web'
|
|
version = '0.0.1-SNAPSHOT'
|
|
|
|
java {
|
|
toolchain {
|
|
languageVersion = JavaLanguageVersion.of(21)
|
|
}
|
|
}
|
|
|
|
repositories {
|
|
mavenCentral()
|
|
}
|
|
|
|
dependencies {
|
|
implementation 'org.springframework.boot:spring-boot-starter-actuator'
|
|
implementation 'org.springframework.boot:spring-boot-starter-webflux'
|
|
|
|
testImplementation 'org.springframework.boot:spring-boot-starter-webflux-test'
|
|
testRuntimeOnly 'org.junit.platform:junit-platform-launcher'
|
|
|
|
implementation 'com.github.oshi:oshi-core:7.7.2'
|
|
}
|
|
|
|
tasks.named('test') {
|
|
useJUnitPlatform()
|
|
}
|
|
|
|
def frontendDir = file('../frontend')
|
|
def frontendDistDir = file('../frontend/dist/frontend/browser')
|
|
def springStaticDir = file('src/main/resources/static')
|
|
|
|
tasks.register('installFrontendDependencies', Exec) {
|
|
workingDir frontendDir
|
|
|
|
inputs.file(file('../frontend/package.json'))
|
|
inputs.file(file('../frontend/package-lock.json'))
|
|
outputs.dir(file('../frontend/node_modules'))
|
|
|
|
if (System.getProperty('os.name').toLowerCase().contains('windows')) {
|
|
commandLine 'cmd', '/c', 'npm', 'ci'
|
|
} else {
|
|
commandLine 'npm', 'ci'
|
|
}
|
|
}
|
|
|
|
tasks.register('buildFrontend', Exec) {
|
|
dependsOn 'installFrontendDependencies'
|
|
workingDir frontendDir
|
|
|
|
inputs.dir(file('../frontend/src'))
|
|
inputs.file(file('../frontend/angular.json'))
|
|
inputs.file(file('../frontend/tsconfig.json'))
|
|
|
|
outputs.dir(frontendDistDir)
|
|
|
|
if (System.getProperty('os.name').toLowerCase().contains('windows')) {
|
|
commandLine 'cmd', '/c', 'npm', 'run', 'build', '--', '--configuration', 'production'
|
|
} else {
|
|
commandLine 'npm', 'run', 'build', '--', '--configuration', 'production'
|
|
}
|
|
}
|
|
|
|
// Skip frontend build tasks when building inside Docker (frontend already built in Stage 1)
|
|
def skipFrontend = project.hasProperty('skipFrontend') || System.getenv('SKIP_FRONTEND') != null
|
|
|
|
tasks.register('copyFrontend', Copy) {
|
|
onlyIf { !skipFrontend }
|
|
dependsOn 'buildFrontend'
|
|
outputs.upToDateWhen { false }
|
|
|
|
doFirst {
|
|
fileTree(springStaticDir).matching {
|
|
include 'main-*.js', 'polyfills-*.js', 'chunk-*.js', 'styles-*.css'
|
|
}.files.each { it.delete() }
|
|
}
|
|
|
|
from(frontendDistDir)
|
|
into(springStaticDir)
|
|
}
|
|
|
|
tasks.named('processResources') {
|
|
dependsOn 'copyFrontend'
|
|
}
|